Fonts don't load in the pdf viewer - c#

I have currently a problem with PdfSharp/MigraDoc and a pdf viewer. I have used the EZFontResolver made by Thomas to be able to generate pdfs with custom fonts. Unfortunately the pdf viewer is unable to render the font, and I have no idea why. I have seen a bug described by Travis on Thomas' blog, which noted, that if EZFontResolver doesn't have multiple bold/italic symbol recognition (for example "fontname|b|b"), than PdfDocumentRenderer.RenderDocument() fails. The point is, when I try something like this:
Document document = DdlReader.DocumentFromString(ddl);
_renderer = new DocumentRenderer(document);
_renderer.PrepareDocument();
than the EZFontResolver is being asked for fonts with names like "customfont|b|b" (it doesn't happen when I use only PdfDocument.Save(...)) instead of "customfont".
My pdf viewer overrides DocumentViewer and views FixedDocument class instances. The funny thing is that the saved pdf file has all the fonts set, but the preview is unable to do that (and that is my big problem). All of this happens even though I return the right font with the resolver.
EDIT:
The ddl is a string which looks something like this:
"\\document
[
Info
{
Title = \"My file\"
Subject = \"My pdf file\"
Author = \"mikes\"
}
]
{
\\styles
{
Heading1 : Normal
{
Font
{
Name = \"My custom font\"
Bold = true
}
ParagraphFormat
{
Alignment = Center
SpaceBefore = \"0.5cm\"
SpaceAfter = \"0.5cm\"
}
}
header : Normal
{
Font
{
Name = \"My custom font\"
Size = 6
}
ParagraphFormat
{
Alignment = Center
}
}
And when I deleted the bug fix by Travis, the exception was thrown in the _renderer.PrepareDocument() (after fix, the stack trace showed that the source of multiple "|b" was also out of there).

Simulated bold and simulated italics use the regular font, but a transformation is applied.
Therefore the simulation will not work if the PDF viewer does not support those transformations.
The DocumentViewer that comes with MigraDoc does not display PDF files, it displays MigraDoc documents. For technical reasons it cannot use fonts supplied via the IFontResolver interface. EZFontResolver is an implementation of IFontResolver.
With respect to "customfont|b|b": I cannot say whether this is a bug or the regular behaviour. Please provide an MCVE (complete sample) if you think it is a bug.

Related

c# , how to generate password protected arabic pdf or word document

I used Itext7 in my C# code to create a pdf file, as I said in my other question here
Itext7 not showing arabic text
so I gave up on trying to fix it, because it seems like I need to pay for the addon, and I can't do that
I tried Pdf sharp, it showed arabic letters but there were disconnected and reversed, and writing arabic backward did not make the letters connect
I used SautinSoft library and it created a word document where arabic works fine, but it has a footer that says that it is a free version, so i can't use this one either
the pdf created by this library also doesnt support arabic
so I think I can't write pdf in arabic, all libraries I tried didn't supported it
is there anyway to fix it?
or can anyone please suggest another library that can create arabic pdf or a word document without watermarks or footers
I found the solution, using Gembox pdf, it only allows 20 paragraphs, but that is more than enough
What if DocumentCore?
public static void SecureDocument()
{
string filePath = #"ProtectedDocument.pdf";
DocumentCore dc = new DocumentCore();
// Let's create a simple document.
dc.Content.End.Insert("Hello World!!!", new CharacterFormat() { FontName = "Verdana", Size = 65.5f, FontColor = Color.Orange });
PdfSaveOptions so = new PdfSaveOptions();
// Password Protection
so.EncryptionDetails.UserPassword = "12345";
// EncryptionAlgorithm
so.EncryptionDetails.EncryptionAlgorithm = PdfEncryptionAlgorithm.RC4_128;
//Permissions: Content Copying, Commenting, Printing, Changing the Document, filing of form fildes
//Printing: Allowed
so.EncryptionDetails.Permissions = PdfPermissions.Printing;
// Save a document as the PDF file with Security Options.
dc.Save(filePath, so);
// Open the result for demonstration purposes.
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(filePath) { UseShellExecute = true });
}

Exporting WPF Canvas to PDF

I've been attempting to find an easy solution to exporting a Canvas in my WPF Application to a PDF Document.
So far, the best solution has been to use the PrintDialog and set it up to automatically use the Microsoft Print the PDF 'printer'. The only problem I have had with this is that although the PrintDialog is skipped, there is a FileDialog to choose where the file should be saved.
Sadly, this is a deal-breaker because I would like to run this over a large number of canvases with automatically generated PDF names (well, programitically provided anyway).
Other solutions I have looked at include:
Using PrintDocument, but from my experimentation I would have to manually iterate through all my Canveses children and manually invoke the correct Draw method (of which a lot of my custom elements with transformation would be rather time consuming to do)
Exporting as a PNG image and then embedding that in a PDF. Although this works, TextBlocks within my canvas are no longer text. So this isn't an ideal situation.
Using the 3rd party library PDFSharp has the same downfall as the PrintDocument. A lot of custom logic for each element.
With PDFSharp. I did find a method fir generating the XGraphics from a Canvas but no way of then consuming that object to make a PDF Page
So does anybody know how I can skip or automate the PDF PrintDialog, or consume PDFSharp XGraphics to make
A page. Or any other ideas for directions to take this besides writing a whole library to convert each of my Canvas elements to PDF elements.
If you look at the output port of a recent windows installation of Microsoft Print To PDF
You may note it is set to PORTPROMP: and that is exactly what causes the request for a filename.
You might note lower down, I have several ports set to a filename, and the fourth one down is called "My Print to PDF"
So very last century methodology; when I print with a duplicate printer but give it a different name I can use different page ratios etc., without altering the built in standard one. The output for a file will naturally be built:-
A) Exactly in one repeatable location, that I can file monitor and rename it, based on the source calling the print sequence, such that if it is my current default printer I can right click files to print to a known \folder\file.pdf
B) The same port can be used via certain /pt (printto) command combinations to output, not just to that default port location, but to a given folder\name such as
"%ProgramFiles%\Windows NT\Accessories\WORDPAD.EXE" /pt listIN.doc "My Print to PDF" "My Print to PDF" "listOUT.pdf"
Other drivers usually charge for the convenience of WPF programmable renaming, but I will leave you that PrintVisual challenge for another of your three wishes.
MS suggest XPS is best But then they would be promoting it as a PDF competitor.
It does not need to be Doc[X]2PDF it could be [O]XPS2PDF or aPNG2PDF or many pages TIFF2PDF etc. etc. Any of those are Native to Win 10 also other 3rd party apps such as [Free]Office with a PrintTo verb will do XLS[X]2PDF. Imagination becomes pagination.
I had a great success in generating PDFs using PDFSharp in combination with SkiaSharp (for more advanced graphics).
Let me begin from the very end:
you save the PdfDocument object in the following way:
PdfDocument yourDocument = ...;
string filename = #"your\file\path\document.pdf"
yourDocument.Save(filename);
creating the PdfDocument with a page can be achieved the following way (adjust the parameters to fit your needs):
PdfDocument yourDocument = new PdfDocument();
yourDocument.PageLayout = PdfPageLayout.SinglePage;
yourDocument.Info.Title = "Your document title";
PdfPage yourPage = yourDocument.AddPage();
yourDocument.Orientation = PageOrientation.Landscape;
yourDocument.Size = PageSize.A4;
the PdfPage object's content (as an example I'm putting a string and an image) is filled in the following way:
using (XGraphics gfx = XGraphics.FromPdfPage(yourPage))
{
XFont yourFont = new XFont("Helvetica", 20, XFontStyle.Bold);
gfx.DrawString(
"Your string in the page",
yourFont,
XBrushes.Black,
new XRect(0, XUnit.FromMillimeter(10), page.Width, yourFont.GetHeight()),
XStringFormats.Center);
using (Stream s = new FileStream(#"path\to\your\image.png", FileMode.Open))
{
XImage image = XImage.FromStream(s);
var imageRect = new XRect()
{
Location = new XPoint() { X = XUnit.FromMillimeter(42), Y = XUnit.FromMillimeter(42) },
Size = new XSize() { Width = XUnit.FromMillimeter(42), Height = XUnit.FromMillimeter(42.0 * image.PixelHeight / image.PixelWidth) }
};
gfx.DrawImage(image, imageRect);
}
}
Of course, the font objects can be created as static members of your class.
And this is, in short to answer your question, how you consume the XGraphics object to create a PDF page.
Let me know if you need more assistance.

PDFSharp saved Document always promps the "Save changes" message after filling form fields

Recently I made a program where I take a pdf file and using PDFsharp fill in the form fields with required values. The code that I made works fine it writes the values just fine but the problem comes after you open the pdf and try to close it, you will get a the standard message "Do you want to save changes before closing" even thou you just opened and close the document. The code that I use looks like this:
string templateDocPath = #"Original.pdf";
using (PdfDocument myTemplate = PdfReader.Open(templateDocPath, PdfDocumentOpenMode.Modify))
{
PdfAcroForm form = myTemplate.AcroForm;
if (form.Elements.ContainsKey("/NeedAppearances"))
{
form.Elements["/NeedAppearances"] = new PdfBoolean(true);
}
else
{
form.Elements.Add("/NeedAppearances", new PdfBoolean(true));
}
PdfTextField testField = (PdfTextField)(form.Fields["Name"]);
testField.Value = new PdfString("NameTest");
testField.ReadOnly = true;
myTemplate.Save(#"Output.pdf");
myTemplate.Close();
}
When I was trying to solved the problem I found out that the message comes only after you add "/NeedAppearances" Element to the AcroForms. You need this element or the values you write on the document will not show.
Googling some more I found a forum (https://forum.pdfsharp.net/viewtopic.php?f=2&t=3741) where someone asked the same question but didn't get a clear answer, the last comment mentioned that "/NeedAppearances" says to the document to generate the new values. So when you open the document new values are generated, so you have to save them.
I would like to know if it's true and is there a way to remove the message?
I came across this article yesterday while I was trying to find an answer for the exact problem described in the title. I was never able to find anything from any of the Google searches I ran. However, I was able to figure out what the problem was.
The issue is that when you save the PdfDocument object, it is defaulting the PDF as version 0. You can verify this by opening the generated PDF in Notepad++ (or similar text editor) and looking at the first line. When you open the PDF, Acrobat/Reader has to format it to be able to display it since it is an outdated PDF version; thus causing the document to be changed.
The solution is to set the Version of the PdfDocument before you save (an example of this can be seen here: https://forum.pdfsharp.net/viewtopic.php?f=2&t=617). As of PDFsharp version 1.50, the highest supported version is 17 (see PDFsharp Wiki on which PDF versions are supported).

How do I extract actual font names from a PDF with iTextSharp?

I am using iTextSharp for PDF processing, and I need to extract all text from an existing PDF that is written in a certain font.
A way to do that is to inherit from a RenderFilter and only allow text that has a certain PostscriptFontName. The problem is that when I do this, I see the following font names in the PDF:
CIDFont+F1
CIDFont+F2
CIDFont+F3
CIDFont+F4
CIDFont+F5
which is nothing like the actual font names I am looking for.
I have tried enumerating the font resources, and it shows the same result.
I have tried opening the PDF in the full Adobe Acrobat. It also shows the mangled font names:
I have tried analysing the file with iText RUPS. Same result.
That is, I have not been able to see the actual font names anywhere in the document structure.
Yet, Adobe Acrobat DC does show the correct font names in the Format pane when I select various text boxes on the document canvas (e.g. Arial, Courier New, Roboto), so that information must be stored somewhere.
How do I get those real font names when parsing PDFs with iTextSharp?
As determined in the course of the comments to the question, the font names are anonymized in all PDF metadata for the font but the embedded font program itself contains the actual font name.
(So the PDF strictly speaking is broken, even though in a way hardly any software will ever complain about.)
If we want to retrieve those names, therefore, we have to look inside these font programs.
Here a proof of concept following the architecture used in this answer you referenced, i.e. using a RenderFilter:
class FontProgramRenderFilter : RenderFilter
{
public override bool AllowText(TextRenderInfo renderInfo)
{
DocumentFont font = renderInfo.GetFont();
PdfDictionary fontDict = font.FontDictionary;
PdfName subType = fontDict.GetAsName(PdfName.SUBTYPE);
if (PdfName.TYPE0.Equals(subType))
{
PdfArray descendantFonts = fontDict.GetAsArray(PdfName.DESCENDANTFONTS);
PdfDictionary descendantFont = descendantFonts[0] as PdfDictionary;
PdfDictionary fontDescriptor = descendantFont.GetAsDict(PdfName.FONTDESCRIPTOR);
PdfStream fontStream = fontDescriptor.GetAsStream(PdfName.FONTFILE2);
byte[] fontData = PdfReader.GetStreamBytes((PRStream)fontStream);
MemoryStream dataStream = new MemoryStream(fontData);
dataStream.Position = 0;
MemoryPackage memoryPackage = new MemoryPackage();
Uri uri = memoryPackage.CreatePart(dataStream);
GlyphTypeface glyphTypeface = new GlyphTypeface(uri);
memoryPackage.DeletePart(uri);
ICollection<string> names = glyphTypeface.FamilyNames.Values;
return names.Where(name => name.Contains("Arial")).Count() > 0;
}
else
{
// analogous code for other font subtypes
return false;
}
}
}
The MemoryPackage class is from this answer which was my first find searching for how to read information from a font in memory using .Net.
Applied to your PDF file like this:
using (PdfReader pdfReader = new PdfReader(SOURCE))
{
FontProgramRenderFilter fontFilter = new FontProgramRenderFilter();
ITextExtractionStrategy strategy = new FilteredTextRenderListener(
new LocationTextExtractionStrategy(), fontFilter);
Console.WriteLine(PdfTextExtractor.GetTextFromPage(pdfReader, 1, strategy));
}
the result is
This is Arial.
Beware: This is a mere proof of concept.
On one hand you will surely also need to implement the part commented as analogous code for other font subtypes above; and even the TYPE0 part is not ready for production use as it only considers FONTFILE2 and does not handle null values gracefully.
On the other hand you will want to cache names for fonts already inspected.

MigraDox C# Checkboxes - Wingdings Not Working

I am needing to simulate a checkbox in a PDF I am generating using the MigraDoc library. I stumbled across two sources that offer essentially the same solution (here and here)
However, I am not getting the expected results. Instead I am getting þ for boxes that are supposed to be checked, and ¨ for those that are to be unchecked. What might the issue be?
Snippet of my code
para = section.AddParagraph();
para.Style = "ListLevelOne";
para.AddFormattedText("1 ", "Bold");
para.AddFormattedText(IsQ1Checked ? "\u00fe" : "\u00A8", new Font("Wingdings"));
MigraDoc does not use the font "Wingdings", instead it uses a default font (could be MS Sans or so) and therefore you see the characters from a standard font, not the Wingdings symbol.
The problem is somewhere outside the code snippet you are showing here. Make sure the font Wingdings is installed on the computer.
You may want to embed the font and ensure that MigraDoc uses unicode encoding instead of ansi:
private const bool unicode = true;
private const PdfFontEmbedding embedding = PdfFontEmbedding.Always;
//...
var pdfRenderer = new PdfDocumentRenderer(unicode, embedding);
http://www.pdfsharp.net/wiki/migradochelloworld-sample.ashx

Categories

Resources