using ArkhamPnP.Data; using iText.IO.Image; using iText.Kernel.Pdf; using iText.Layout; using iText.Layout.Element; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Security.Cryptography.Xml; using System.Text; using System.Threading.Tasks; namespace ArkhamPnP { internal class PDFComposer { const float PAGE_WIDTH = 210; // mm const float PAGE_HEIGHT = 297; // mm const float CARD_WIDTH = 63; // mm const float CARD_HEIGHT = 89; // mm const float FRONT_PADDING = 3; // mm const float MARGIN_SIDE = 5; // mm const float MARGIN_TOP_BOTTOM = 5; // mm private ArkhamDBApi api; public PDFComposer() { api = new ArkhamDBApi(); } public async Task PrintCards(List cards, string destinationPath) { var pdfDoc = new PdfDocument(new PdfWriter(destinationPath)); var doc = new Document(pdfDoc, new iText.Kernel.Geom.PageSize(PAGE_WIDTH, PAGE_HEIGHT)); // compute card amount on page int grid_width = 0; while (CARD_WIDTH * (grid_width + 1) + FRONT_PADDING * (grid_width + 1 - 1) + 2 * MARGIN_SIDE <= PAGE_WIDTH) grid_width++; int grid_height = 0; while (CARD_HEIGHT * (grid_height + 1) + FRONT_PADDING * (grid_height + 1 - 1) + 2 * MARGIN_TOP_BOTTOM <= PAGE_HEIGHT) grid_height++; Console.WriteLine("Will produce grid of cards " + grid_height + "x" + grid_width); // compute position of left-top card in page float left = (PAGE_WIDTH - grid_width * CARD_WIDTH - (grid_width - 1) * FRONT_PADDING) / 2; float top = (PAGE_HEIGHT - grid_height * CARD_HEIGHT - (grid_height - 1) * FRONT_PADDING) / 2; // ResourceManager rm = new ResourceManager("ArkhamPnP.Resources", Assembly.GetExecutingAssembly()); byte[] playerBytes = rm.GetObject("player") as byte[]; // int pos = 0; int current_page = 1; while (pos < cards.Count) { while (pdfDoc.GetNumberOfPages() < current_page + 1) { pdfDoc.AddNewPage(new iText.Kernel.Geom.PageSize(PAGE_WIDTH, PAGE_HEIGHT)); } float front_left = left; float front_top = top; float rear_left = left - FRONT_PADDING / 2; float rear_top = top - FRONT_PADDING / 2; for (int i = 0; i < grid_height; i++) { for (int j = 0; j < grid_width; j++) { if (pos >= cards.Count) break; Console.WriteLine("Adding card " + (pos + 1) + " of " + cards.Count); var current_card = cards[pos]; var front_image = await LoadImage(current_card); Image image = new Image(ImageDataFactory.Create(front_image)); image.SetFixedPosition(current_page, front_left, front_top, CARD_WIDTH); pos++; doc.Add(image); front_left += CARD_WIDTH + FRONT_PADDING; // Image backImage = new Image(ImageDataFactory.Create(playerBytes)); backImage.SetFixedPosition(current_page + 1, PAGE_WIDTH - rear_left - (CARD_WIDTH + FRONT_PADDING), rear_top, CARD_WIDTH + FRONT_PADDING); doc.Add(backImage); rear_left += CARD_WIDTH + FRONT_PADDING; } front_left = left; front_top += CARD_HEIGHT + FRONT_PADDING; rear_left = left - FRONT_PADDING / 2; rear_top += CARD_HEIGHT + FRONT_PADDING; if (pos >= cards.Count) break; } current_page += 2; } doc.Close(); } private async Task LoadImage(Card card) { string assembly_folder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var parts = card.image_src.Split('/'); var destination_path = assembly_folder; for (int i = 0; i < parts.Length; i++) destination_path = Path.Combine(destination_path, parts[i]); var directory = Path.GetDirectoryName(destination_path); if (!Directory.Exists(directory)) Directory.CreateDirectory(directory); if (File.Exists(destination_path)) return destination_path; var stream = await api.GetImage(card.image_src); var file_stream = File.Create(destination_path); await stream.CopyToAsync(file_stream); file_stream.Close(); return destination_path; } } }