1
0
Fork 0
mirror of https://github.com/Nioux/AideDeJeu.git synced 2025-10-30 15:06:06 +00:00
AideDeJeu/AideDeJeu/AideDeJeu/Pdf/PdfService.cs
2019-07-29 18:16:42 +02:00

547 lines
19 KiB
C#

using AideDeJeu.Tools;
using AideDeJeu.ViewModels;
using iTextSharp.text;
using iTextSharp.text.pdf;
using Markdig;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace AideDeJeu.Pdf
{
public class PdfService
{
public static PdfService Instance
{
get
{
return DependencyService.Get<PdfService>();
}
}
public static void DrawText(PdfContentByte cb, string text, iTextSharp.text.Font font, float x, float y, float width, float height, int alignment)
{
cb.SetRGBColorFill(127, 127, 127);
//cb.Rectangle(x, y, width, height);
//cb.Stroke();
ColumnText ct = new ColumnText(cb);
ct.SetSimpleColumn(x, y, x + width, y + height);
var p = new Paragraph(text); //, font);
p.Alignment = alignment;
ct.AddElement(p);
ct.Go();
}
public string BasePdfDirectory
{
get
{
return Path.Combine(Xamarin.Essentials.FileSystem.CacheDirectory, "pdf");
}
}
public async Task<string> MarkdownToPDF(IEnumerable<AideDeJeuLib.Item> items)
{
return await MarkdownToPDF(items.Select(it => it.Markdown));
}
public async Task MarkdownToPDF(IEnumerable<AideDeJeuLib.Item> items, Stream stream)
{
await MarkdownToPdf(items.Select(it => it.Markdown), stream);
}
public async Task<string> MarkdownToPDF(IEnumerable<string> mds)
{
var basePath = BasePdfDirectory;
Directory.CreateDirectory(basePath);
using (var stream = new FileStream(Path.Combine(BasePdfDirectory, "test.pdf"), FileMode.Create))
{
await MarkdownToPdf(mds, stream);
}
return "test.pdf";
}
public async Task<string> ExpandMarkdownAsync(string mdIn)
{
var store = DependencyService.Get<StoreViewModel>();
var regex = new Regex("\\n##* \\[.*?\\]\\((?<id>.*?)\\)");
var matches = regex.Matches(mdIn);
var mdOut = mdIn;
foreach (Match match in matches)
{
var id = match.Groups["id"].Value;
var item = await store.GetItemFromDataAsync(id);
var mdReplace = await ExpandMarkdownAsync(item.Markdown);
mdOut = mdOut.Replace(match.Value, mdReplace);
}
return mdOut;
}
public async Task MarkdownToPdf(IEnumerable<string> mds, Stream stream)
{
var pipeline = new Markdig.MarkdownPipelineBuilder().UseYamlFrontMatter().UsePipeTables().Build();
var document = new Document(new iTextSharp.text.Rectangle(822, 1122));
var writer = PdfWriter.GetInstance(document, stream);
document.Open();
//PdfReader reader = null;
//reader = new PdfReader(AideDeJeu.Tools.Helpers.GetResourceStream("AideDeJeu.Pdf.poker_size.pdf"));
//PdfStamper stamper = null;
//stamper = new PdfStamper(reader, stream);
try
{
foreach (var md in mds)
{
var expandedMd = await ExpandMarkdownAsync(md);
var parsed = Markdig.Markdown.Parse(expandedMd, pipeline);
Render(parsed.AsEnumerable(), document, writer);
}
}
catch(Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
try
{
document?.Close();
}
catch
{
}
writer.Close();
}
//stamper.Close();
//reader.Close();
}
private BaseFont GetBaseFont(string fontName)
{
string fontPath = fontName;
if(Xamarin.Essentials.DeviceInfo.Platform != Xamarin.Essentials.DevicePlatform.Unknown)
{
fontPath = Path.Combine(Xamarin.Essentials.FileSystem.CacheDirectory, fontPath);
}
using (var inFont = AideDeJeu.Tools.Helpers.GetResourceStream($"AideDeJeu.Pdf.{fontName}"))
{
using (var outFont = new FileStream(fontPath, FileMode.Create, FileAccess.ReadWrite))
{
inFont.CopyTo(outFont);
}
}
FontFactory.Register(fontPath);
return iTextSharp.text.pdf.BaseFont.CreateFont(fontPath, iTextSharp.text.pdf.BaseFont.IDENTITY_H, iTextSharp.text.pdf.BaseFont.EMBEDDED);
}
BaseFont _CinzelRegular = null;
public BaseFont CinzelRegular
{
get
{
return _CinzelRegular ?? (_CinzelRegular = GetBaseFont("Cinzel-Regular.otf"));
}
}
BaseFont _CinzelBold = null;
public BaseFont CinzelBold
{
get
{
return _CinzelBold ?? (_CinzelBold = GetBaseFont("Cinzel-Bold.otf"));
}
}
BaseFont _LinuxLibertine = null;
public BaseFont LinuxLibertine
{
get
{
return _LinuxLibertine ?? (_LinuxLibertine = GetBaseFont("LinLibertine_R.ttf"));
}
}
iTextSharp.text.Font _Header1Font = null;
public iTextSharp.text.Font Header1Font
{
get
{
return _Header1Font ?? (_Header1Font = new iTextSharp.text.Font(CinzelBold, 30));
}
}
iTextSharp.text.Font _Header2Font = null;
public iTextSharp.text.Font Header2Font
{
get
{
return _Header2Font ?? (_Header2Font = new iTextSharp.text.Font(CinzelRegular, 25));
}
}
iTextSharp.text.Font _Header3Font = null;
public iTextSharp.text.Font Header3Font
{
get
{
return _Header3Font ?? (_Header3Font = new iTextSharp.text.Font(CinzelRegular, 20));
}
}
iTextSharp.text.Font _Header4Font = null;
public iTextSharp.text.Font Header4Font
{
get
{
return _Header4Font ?? (_Header4Font = new iTextSharp.text.Font(CinzelRegular, 18));
}
}
iTextSharp.text.Font _Header5Font = null;
public iTextSharp.text.Font Header5Font
{
get
{
return _Header5Font ?? (_Header5Font = new iTextSharp.text.Font(CinzelRegular, 16));
}
}
iTextSharp.text.Font _Header6Font = null;
public iTextSharp.text.Font Header6Font
{
get
{
return _Header6Font ?? (_Header6Font = new iTextSharp.text.Font(CinzelRegular, 15));
}
}
iTextSharp.text.Font _ParagraphFont = null;
iTextSharp.text.Font ParagraphFont
{
get
{
return _ParagraphFont ?? (_ParagraphFont = new iTextSharp.text.Font(LinuxLibertine, 15));
}
}
private void Render(IEnumerable<Block> blocks, Document document, PdfWriter writer)
{
//if(ParagraphFont == null)
//{
// if(CinzelRegular == null)
// {
// }
// //var fontPath = Path.Combine(Xamarin.Essentials.FileSystem.CacheDirectory, "Cinzel-Regular.otf");
// //var fontPath = @"C:\Users\yanma\Documents\Visual Studio 2017\Projects\AideDeJeu\AideDeJeu\AideDeJeuCmd\bin\Debug\netcoreapp2.1\Cinzel-Regular.otf";
// var fontPath = @"Cinzel-Regular.otf";
// using (var inFont = AideDeJeu.Tools.Helpers.GetResourceStream("AideDeJeu.Pdf.Cinzel-Regular.otf"))
// {
// using (var outFont = new FileStream(fontPath, FileMode.Create, FileAccess.ReadWrite))
// {
// inFont.CopyTo(outFont);
// }
// }
// FontFactory.Register(fontPath);
// //var mafont = FontFactory.GetFont("cinzel", 20, iTextSharp.text.Font.NORMAL);
// var mafont = iTextSharp.text.pdf.BaseFont.CreateFont(fontPath, iTextSharp.text.pdf.BaseFont.IDENTITY_H, iTextSharp.text.pdf.BaseFont.EMBEDDED);
// //var font = mafont.BaseFont;
// var bigFont = new iTextSharp.text.Font(mafont, 20);
// var fonts = FontFactory.RegisteredFonts;
// ParagraphFont = bigFont;
//}
var phrases = Render(blocks);
ColumnText ct = new ColumnText(writer.DirectContent);
int column = 0;
ct.SetSimpleColumn(10, 10 + 200 * column, 200, 200 + 200 * column);
int status = 0;
Phrase p = null;
float y = 0;
foreach (var phrase in phrases)
{
//var pphrase = new Phrase("test", bigFont);
//phrase.Font = ParagraphFont;
y = ct.YLine;
document.Add(phrase);
//ct.AddText(phrase);
//status = ct.Go(true);
//if(ColumnText.HasMoreText(status))
//{
// column++;
// ct.SetSimpleColumn(10, 10 + 200 * column, 200, 200 + 200 * column);
// y += 200;
//}
//ct.YLine = y;
//ct.SetText(phrase);
//status = ct.Go(false);
//ColumnText ct = new ColumnText(_Writer.DirectContent);
//ct.AddText(CreateFormatted(block.Inline, Font.HELVETICA, 0, new Color(0, 0, 0), 12));
//ct.Alignment = Element.ALIGN_JUSTIFIED;
//ct.SetSimpleColumn(10, 10, 200, 200);
//ct.Go();
}
}
private IEnumerable<Phrase> Render(IEnumerable<Block> blocks)
{
var phrases = new List<Phrase>();
foreach (var block in blocks)
{
var phrase = this.Render(block);
if(phrase != null)
{
phrases.Add(phrase);
}
if (block.IsBreakable)
{
phrases.Add(new Phrase(Chunk.NEWLINE));
}
}
return phrases;
}
private Phrase Render(Block block)
{
switch (block)
{
case HeadingBlock heading:
return Render(heading);
case ParagraphBlock paragraph:
return Render(paragraph);
//case QuoteBlock quote:
// Render(quote);
// break;
//case CodeBlock code:
// Render(code);
// break;
case ListBlock list:
return Render(list);
//break;
//case ThematicBreakBlock thematicBreak:
// Render(thematicBreak);
// break;
//case HtmlBlock html:
// Render(html);
// break;
case Markdig.Extensions.Tables.Table table:
return Render(table);
//break;
default:
Debug.WriteLine($"Can't render {block.GetType()} blocks.");
return null;
}
//if (queuedViews.Any())
//{
// foreach (var view in queuedViews)
// {
// this.stack.Children.Add(view);
// }
// queuedViews.Clear();
//}
}
private Phrase Render(HeadingBlock block)
{
var fonts = new iTextSharp.text.Font[] { Header1Font, Header2Font, Header3Font, Header4Font, Header5Font, Header6Font };
var colors = new iTextSharp.text.Color[] { new iTextSharp.text.Color(0x9B1C47), new iTextSharp.text.Color(0, 0, 0), new iTextSharp.text.Color(0, 0, 0), new iTextSharp.text.Color(0, 0, 0), new iTextSharp.text.Color(0, 0, 0), new iTextSharp.text.Color(0, 0, 0) };
return CreateFormatted(block.Inline, fonts[block.Level - 1], 0, colors[block.Level - 1]);
}
private Phrase Render(ParagraphBlock block)
{
return CreateFormatted(block.Inline, ParagraphFont, 0, new iTextSharp.text.Color(0, 0, 0));
//_Document.Add(CreateFormatted(block.Inline, Font.HELVETICA, 0, new Color(0, 0, 0), 20));
}
private Phrase Render(ListBlock block)
{
//listScope++;
var views = new Phrase();
for (int i = 0; i < block.Count(); i++)
{
var item = block.ElementAt(i);
if (item is ListItemBlock itemBlock)
{
var subviews = this.Render(block, i + 1, itemBlock);
if (subviews != null)
{
views.AddRange(subviews);
}
}
}
//listScope--;
return views;
}
private Phrase Render(ListBlock parent, int index, ListItemBlock block)
{
var stack = new Phrase();
var subv = this.Render(block.AsEnumerable());
subv.ToList().ForEach(v => stack.Add(v));
return stack;
}
private Phrase Render(Markdig.Extensions.Tables.Table tableBlock)
{
int maxColumns = 0;
foreach (Markdig.Extensions.Tables.TableRow row in tableBlock)
{
maxColumns = Math.Max(maxColumns, row.Count);
}
var table = new PdfPTable(maxColumns);
foreach (Markdig.Extensions.Tables.TableRow row in tableBlock)
{
foreach (Markdig.Extensions.Tables.TableCell cell in row)
{
var phrase = new Phrase();
foreach (var blockpar in cell)
{
var par = blockpar as Markdig.Syntax.ParagraphBlock;
var blockPhrase = CreateFormatted(par.Inline, ParagraphFont, 0, new iTextSharp.text.Color(0));
phrase.Add(blockPhrase);
}
table.AddCell(phrase);
}
}
var tablePhrase = new Phrase();
tablePhrase.Add(table);
return tablePhrase;
}
private Phrase CreateFormatted(ContainerInline inlines, iTextSharp.text.Font fontFamily, int fontStyle, iTextSharp.text.Color fontColor)
{
var phrase = new Phrase();
foreach (var inline in inlines)
{
var spans = CreateChunks(inline, fontFamily, fontStyle, fontColor);
if (spans != null)
{
foreach (var span in spans)
{
phrase.Add(span);
}
}
}
return phrase;
}
private IEnumerable<Chunk> CreateChunks(Inline inline, iTextSharp.text.Font fontFamily, int fontStyle, iTextSharp.text.Color fontColor)
{
switch (inline)
{
case LiteralInline literal:
return new Chunk[]
{
new Chunk()
{
Content = literal.Content.Text.Substring(literal.Content.Start, literal.Content.Length),
Font = new iTextSharp.text.Font(fontFamily.BaseFont, fontFamily.Size, fontStyle, fontColor)
}
};
case EmphasisInline emphasis:
var childStyle = fontStyle | (emphasis.DelimiterCount == 2 ? iTextSharp.text.Font.BOLD : iTextSharp.text.Font.ITALIC);
var espans = emphasis.SelectMany(x => CreateChunks(x, fontFamily, childStyle, fontColor));
return espans.ToArray();
case LineBreakInline breakline:
return new Chunk[] { Chunk.NEWLINE };
case LinkInline link:
return link.SelectMany(x => CreateChunks(x, fontFamily, fontStyle, fontColor));
case CodeInline code:
case HtmlInline html:
default:
return new Chunk[] { };
}
//var cb = stamper.GetOverContent(1);
////ColumnText.ShowTextAligned(cb, iTextSharp.text.Element.ALIGN_LEFT, new Phrase("Galefrin"), 40, 40, 0);
//ColumnText ct = new ColumnText(cb);
//ct.SetSimpleColumn(10f, 48f, 200f, 600f);
//Font f = new Font();
//Paragraph pz = new Paragraph(new Phrase(20, "Hello World!", f));
//ct.AddElement(pz);
//ct.Go();
//BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, "Cp1252", BaseFont.EMBEDDED);
//f = new Font(bf, 13);
//ct = new ColumnText(cb);
//ct.SetSimpleColumn(10f, 48f, 200f, 700f);
//pz = new Paragraph("Hello World!", f);
//ct.AddElement(pz);
//ct.Go();
//return;
/*
var text = block.ToMarkdownString();
//DrawText(content, md, null, 100, 100, 300, 300, 0);
float x = 10;
float y = 10;
float width = 300;
float height = 300;
cb.SetRGBColorFill(127, 127, 127);
//cb.Rectangle(x, y, width, height);
//cb.Stroke();
ColumnText ct = new ColumnText(cb);
ct.SetSimpleColumn(x, y, x + width, y + height);
Font font = new Font(BaseFont.CreateFont());
//int rectWidth = 80;
//float maxFontSize = getMaxFontSize(BaseFont.CreateFont(), "text", rectWidth);
font.Size = 20;
var p = new Paragraph(text, font);
//p.Alignment = alignment;
ct.AddElement(p);
ct.Go();
//var style = this.Theme.Paragraph;
//var foregroundColor = isQuoted ? this.Theme.Quote.ForegroundColor : style.ForegroundColor;
//var label = new Label
//{
// FormattedText = CreateFormatted(block.Inline, style.FontFamily, style.Attributes, foregroundColor, style.BackgroundColor, style.FontSize),
//};
//AttachLinks(label);
//this.stack.Children.Add(label);
*/
}
}
}