<commit_before>﻿using System;
using FormEngine.Interfaces;
using PdfSharp.Pdf;
using PdfSharp.Drawing;
using PdfSharp.Drawing.Layout;
using System.Drawing;
using System.IO;
using System.Collections.Generic;

namespace FormEngine.PdfFormBuilder
{
    internal class Page : IFormPage
    {
        private Document document;
        private PdfPage page;
        XGraphics xGraphics;

        public Page(Document document, PdfDocument pdfDocument, PageSize pageSize)
        {
            this.document = document;
            page = pdfDocument.AddPage();
            page.Size = ConvertToPdfSharpPageSize(pageSize);
            xGraphics = XGraphics.FromPdfPage(page);
        }

        public void AddImage(IResources files, string file, decimal x, decimal y, decimal width, decimal height)
        {
            XImage xImg = MakeXImage(files, file);
            XRect rectangle = new XRect() { X = XUnit.FromCentimeter((double)x), Y = XUnit.FromCentimeter((double)y), Width = XUnit.FromCentimeter((double)width), Height = XUnit.FromCentimeter((double)height) };
            xGraphics.DrawImage(xImg, rectangle);
        }

        private static Dictionary<string, XImage> imageCache = new Dictionary<string, XImage>();
        private static XImage MakeXImage(IResources files, string file)
        {
            XImage xImg;
            if (!imageCache.TryGetValue(file, out xImg))
            {
                byte[] imgFile = files.Get(file);
                Stream imgStream = new MemoryStream(imgFile);
                System.Drawing.Image image = System.Drawing.Image.FromStream(imgStream);
                xImg = XImage.FromGdiPlusImage(image);
                imageCache[file] = xImg;
            }
            return xImg;
        }

        public void AddText(string fieldName, string text, string alignment, string font, decimal fontSize, Interfaces.FontStyle fontStyle, ColourName colour, decimal x, decimal y, decimal width, decimal height)
        {
            XFontStyle style = ConvertFontStyle(fontStyle);
            XFont xFont = new XFont(font, (double) fontSize, style);
            XRect rectangle = new XRect() { X = XUnit.FromCentimeter((double)x), Y = XUnit.FromCentimeter((double)y) };
            XBrush brush = CreateXBrush(colour);

            if (width > 0)
            {
                XTextFormatter textFormatter = new XTextFormatter(xGraphics);

                rectangle.Width = XUnit.FromCentimeter((double)width);
                if (height <= 0)
                    rectangle.Height = XUnit.FromCentimeter(50);
                else
                    rectangle.Height = XUnit.FromCentimeter((double)height);

                textFormatter.Alignment = GetXParagraphAlignment(alignment);

                textFormatter.DrawString(text, xFont, brush, rectangle, XStringFormats.TopLeft);
            }
            else
            {
                XStringFormat format = new XStringFormat() { Alignment = XStringAlignment.Near };

                xGraphics.DrawString(text, xFont, brush, rectangle, format);
            }
        }

        private const double wastedSpaceFactor = 18; // Higher number gives higher factor
        public decimal MeasureTextHeight(string text, string font, decimal fontSize, Interfaces.FontStyle fontStyle, decimal width, decimal height)
        {
            XFontStyle style = ConvertFontStyle(fontStyle);
            XFont xFont = new XFont(font, (double)fontSize, style);

            var lines = text.Split('\n');

            double totalHeight = 0;
            if (width == 0M)
                width = 9999;

            foreach (string line in lines)
            {
                XSize size = xGraphics.MeasureString(line, xFont);
                if (size.Height > 0)
                {
                    if (size.Width > XUnit.FromCentimeter((double)width))
                    {
                        double charactersPrLine = line.Length / (size.Width / XUnit.FromCentimeter((double)width));
                        double factor = wastedSpaceFactor / charactersPrLine;
                        double numberOfLines = Math.Ceiling(size.Width * (1 + factor) / XUnit.FromCentimeter((double)width));
                        double h = size.Height * numberOfLines;
                        totalHeight += h;
                    }
                    else
                    {
                        totalHeight += size.Height;<commit_msg>Consider fixed text height when estimating text height<commit_after>﻿using System;
using FormEngine.Interfaces;
using PdfSharp.Pdf;
using PdfSharp.Drawing;
using PdfSharp.Drawing.Layout;
using System.Drawing;
using System.IO;
using System.Collections.Generic;

namespace FormEngine.PdfFormBuilder
{
    internal class Page : IFormPage
    {
        private Document document;
        private PdfPage page;
        XGraphics xGraphics;

        public Page(Document document, PdfDocument pdfDocument, PageSize pageSize)
        {
            this.document = document;
            page = pdfDocument.AddPage();
            page.Size = ConvertToPdfSharpPageSize(pageSize);
            xGraphics = XGraphics.FromPdfPage(page);
        }

        public void AddImage(IResources files, string file, decimal x, decimal y, decimal width, decimal height)
        {
            XImage xImg = MakeXImage(files, file);
            XRect rectangle = new XRect() { X = XUnit.FromCentimeter((double)x), Y = XUnit.FromCentimeter((double)y), Width = XUnit.FromCentimeter((double)width), Height = XUnit.FromCentimeter((double)height) };
            xGraphics.DrawImage(xImg, rectangle);
        }

        private static Dictionary<string, XImage> imageCache = new Dictionary<string, XImage>();
        private static XImage MakeXImage(IResources files, string file)
        {
            XImage xImg;
            if (!imageCache.TryGetValue(file, out xImg))
            {
                byte[] imgFile = files.Get(file);
                Stream imgStream = new MemoryStream(imgFile);
                System.Drawing.Image image = System.Drawing.Image.FromStream(imgStream);
                xImg = XImage.FromGdiPlusImage(image);
                imageCache[file] = xImg;
            }
            return xImg;
        }

        public void AddText(string fieldName, string text, string alignment, string font, decimal fontSize, Interfaces.FontStyle fontStyle, ColourName colour, decimal x, decimal y, decimal width, decimal height)
        {
            XFontStyle style = ConvertFontStyle(fontStyle);
            XFont xFont = new XFont(font, (double) fontSize, style);
            XRect rectangle = new XRect() { X = XUnit.FromCentimeter((double)x), Y = XUnit.FromCentimeter((double)y) };
            XBrush brush = CreateXBrush(colour);

            if (width > 0)
            {
                XTextFormatter textFormatter = new XTextFormatter(xGraphics);

                rectangle.Width = XUnit.FromCentimeter((double)width);
                if (height <= 0)
                    rectangle.Height = XUnit.FromCentimeter(50);
                else
                    rectangle.Height = XUnit.FromCentimeter((double)height);

                textFormatter.Alignment = GetXParagraphAlignment(alignment);

                textFormatter.DrawString(text, xFont, brush, rectangle, XStringFormats.TopLeft);
            }
            else
            {
                XStringFormat format = new XStringFormat() { Alignment = XStringAlignment.Near };

                xGraphics.DrawString(text, xFont, brush, rectangle, format);
            }
        }

        private const double wastedSpaceFactor = 18; // Higher number gives higher factor
        public decimal MeasureTextHeight(string text, string font, decimal fontSize, Interfaces.FontStyle fontStyle, decimal width, decimal height)
        {
            if (height > 0)
                return height;

            XFontStyle style = ConvertFontStyle(fontStyle);
            XFont xFont = new XFont(font, (double)fontSize, style);

            var lines = text.Split('\n');

            double totalHeight = 0;
            if (width == 0M)
                width = 9999;

            foreach (string line in lines)
            {
                XSize size = xGraphics.MeasureString(line, xFont);
                if (size.Height > 0)
                {
                    if (size.Width > XUnit.FromCentimeter((double)width))
                    {
                        double charactersPrLine = line.Length / (size.Width / XUnit.FromCentimeter((double)width));
                        double factor = wastedSpaceFactor / charactersPrLine;
                        double numberOfLines = Math.Ceiling(size.Width * (1 + factor) / XUnit.FromCentimeter((double)width));
                        double h = size.Height * numberOfLines;
                        totalHeight += h;
                    }
                    else
                    {
                        totalHeight += size.Height;
{'fraction_non_alphanumeric': 0.08661680991182051, 'fraction_numerical': 0.0032369684116530864, 'mean_word_length': 1.9425287356321839, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5286984', 'n_tokens_mistral': 2328, 'n_tokens_neox': 2193, 'n_words': 567}