Files
ArkhamPnP/PDFComposer.cs

113 lines
4.0 KiB
C#

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<Card> 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<string> 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;
}
}
}