Adobe Reader cannot read fonts from my project? - spring-boot

I am generating the PDF using iTextPdf version 5 and am using Calibri font inside that PDF. I have loaded that font from the src/resource/fonts folder as I am working with Boot. All is working fine as I can view that PDF in my project and download also except that when I am trying to open the PDF using Adobe Reader, than the page is showing something like that-
I have opened that PDF using Google Chrome, WPS office and other PDF Reader and that PDF is working perfectly fine but I can't seem to understand what is wrong when I am trying to view the PDF using Adobe. I have also attached the screenshot of PDF in WPS office below -
Here is the code that I have loaded the font in my PDF -
static URL calibriFont = UserProfileController.class.getResource("/static/fonts/Calibri Regular.ttf");
static Font namefont = FontFactory.getFont(calibriFont.toString(), 20, Font.BOLD, new BaseColor(139, 0, 0));
FontFactory.register(calibriFont.toString());
Here is the PDF File link shared below -
Sample PDF

In short
Additional data was added to the PDF after initial generation, introducing a cross reference error. Take the first 1019493 bytes of the file to get the original working file.
My first guess would be another program postprocessing the PDF incorrectly but as it turned out the iText objects were closed incorrectly resulting in that error.
In detail
The final version of the PDF you shared is not generated by iText, at least not by correct iText usage.
The file has a size of 1021972 bytes. The initial 1019493 bytes constitute a valid PDF.
The extra 2479 bytes extend the PDF providing some updated old object, some new objects, and a full cross reference table. And in this cross reference table the offset entry for the first new object 33 is incorrect, it should be 0001019493 (the first byte added after the original contents, i.e. the start of the first new object) but it is 0001018667 (the start of the cross reference table of the original PDF).
Thus, a PDF processor will incorrectly find the original cross references when looking for the new object 33.
As the object 33 happens to contain the FontDescriptor of the font Calibri in the updated object 1, an attempt to parse this font fails. This font is referenced from all document pages.
As a results, Adobe Reader stops drawing each page as soon as it comes across an instruction using that font.
Some other PDF viewers repair that error under the hood and, therefore, show you what you want to see.
The actual cause
In a comment you write
The error was coming due to PdfWriter instance object was closed before document.
Indeed, you are not expected to close the PdfWriter at all, and in particular not before the Document.
When requesting a PdfWriter using PdfWriter.getInstance for a Document, a PdfDocument instance is created and registered as listener of the Document; then a PdfWriter is created and registered as listener of the PdfDocument.
To finalize the PDF generation you are expected to close the Document. This will call its listeners' respective close methods, i.e. PdfDocument.close, which will finish some last objects, write them, and then call its own listener's close method, i.e. PdfWriter.close, which will write the cross references.
In your code you first explicitly called PdfWriter.close (which wrote the first cross reference table) and then Document.close (which caused PdfDocument to write some objects and then trigger PdfWriter.close again to write the second cross references). This incorrect sequence also resulted in an incorrect cross reference offset.

I have found the solution of my problem as what I was doing that, I have closed PdfWriter instance before the document. When I closed that instance after the document, it was working fine.

Related

How to prevent rendering artifacts in PDFKit/NSImage?

I'm trying to create a tool to rasterise vector images—stored in PDF files—on macOS, but the resulting images contain artifacts around the edges of some shapes. Preview.app, on the other hand, always renders the PDF flawlessly, as shown in this example:
I've tried:
Loading the PDF document using PDFKit, and rendering the page using both draw(with:to:) and thumbnail(of:for:)
Loading the PDF document into an NSImage (which creates an NSPDFImageRep), and using cgImage(forProposedRect:context:hints:)
In both cases I get these aliasing-like artifacts as seen on the left-hand-side of the image above. The PDF file is out of my control, so can't be changed to fix any issues it might have. I'm currently trying to migrate away from Cairo (which renders correctly) to Apple's PDF rendering for performance reasons (PDFKit renders it much more quickly, albeit with these artifacts).
Is there anything I've missed which would fix the output?
So it looks like the issue was caused due to me rasterising PDFs on multiple threads (specifically my tool rasterises PDFs in multiple resolutions, so I thought why not simultaneously).
Performing the operations sequentially on the main thread instead fixed it. I thought that I had come up with a way to use it concurrently by initialising the CGContext manually (instead of using NSImage's lockFocus()/unlockFocus() and NSGraphicsContext.current), but alas, as I soon as I add a context.scaleBy (to generate the images at different sizes), it fails again.
So for now I'm just doing it on the main thread until another solution comes along.

PDFDocument(data: myPdfDoc.dataRepresentation()) does not reproduce original PDF

I encounter a weird bug using PDFKit's PDFDocument.
I have an app with a PDFView and the user can drag & drop a PDF on it.
On this event, I save the data representation (NSData) in my core-data structure
myCoreDataObject.pdfdata = myPDFView.dataRepresentation()
Later, the user can select the core data object to display the PDF, which calls
myPDFView.setDocument(PDFDocument(data: myCoreDataObject.pdfdata))
The PDF is correctly displayed in the PDFView BUT when the user selects text in it, copy-pastes it in another editor, the selection is made of empty(blank) characters ! Which was not the case with the original dragged-and-dropped PDF.
So my question is: WHY this code:
PDFDocument(data: myPdfDoc.dataRepresentation())
does not return the exact same PDF ?
IMPORTANT NOTE: this only happens with OCR'd PDF that have been through ABBY FineReader OCR.
Additional information: the "modification" in the PDF only appears when the binary data goes through core data. I ran a test by directly calling
PDFDocument(data: PDFDocument(url: myUrl).dataRepresentation())
, and the PDF works as expected.

C# PDFsharp end of page detection

Is it possible to detect the end of page in creating PDF file with PDFsharp library? How? Or overflowing text on page? I am generating PDF file with list of users and if the list is too long, I need to add new page and continue on it. I don't want to write ugly code, I want it to be as automatic as possible.
I am aware of MigraDoc library, but I already have a lot of code written in PDFsharp, so if it's not necessary to use MigraDoc (which seems to be better), I would rather stay with PDFsharp. Thanks.
When using PDFsharp, you are responsible to detect the end of page and create a new page for the continuation.
We always say that PDFsharp is low level: no automatic page breaks, but anything can be drawn anywhere.
Still you can write clean code with PDFsharp that handles page breaks properly.
You always have a current page, a current gfx, and a current y position on the page. So when you have to start a new page, re-initialize those variables.

Debugging PDF for error

I'm creating PDF files using PDFClown java library.
Sometimes, when openning these files with Adobe Acrobat Reader I get the famous error message:
"An error exists on this page. Acrobat may not display the page correctly. Please contact the person who created the PDF document to correct the problem."
The error shows while reading (with Adobe) the attached file only when scrolling down to the 8'th page, then scrolling back up to 3'td page. Alternatively, Zooming out to 33.3% will also produce the message.
Just for the record, Foxit reader reads the file flawlessly, as well as other PDF readers like browsers.
My questions are:
What's wrong with my file?? (file is attached)
How can I find what's wrong with it? is there a tool which tells you where does the error lie?
Thanks!
Ok, this wasn't easy -
Due to a bug in PDFClown the my main stream of information in the PDF page has been corrupted.
After it's end it had a copy of a past instance of it.
This caused a partial text section without the starting command "BT" - which left a single "ET" without a "BT" in the end of the stream.
once I corrected this, it ran great.
Thank you all for your help.
I would have much more difficult time debugging it without the tool RUPS which #Bruno suggested.
edit:
The bug was in the Buffer.java:clone() (line 217)
instead of line:
clone.append(data);
needs to be:
clone.append(data, 0, this.length);
Without this correction it clones the whole data buffer, and set the cloned Buffer's length to the data[].length. This is very problematic if the Buffer.length is smaller than the data[].length.
The result in my case was that in the end of the stream there was garbage.
The error shows while reading (with Adobe) the attached file only when scrolling down to the 8'th page, then scrolling back up to 3'td page. Alternatively, Zooming out to 33.3% will also produce the message.
Well, I get it easier, I merely open the PDF and scroll down using the cursor keys. As soon as the top 2 cm of page 3 appear, the message appears.
What's wrong with my file??
The content of pages 1 and 2 look ok, so let's look at the content of page 3.
My initial attributing the issue to the use of text specific operations (especially Tf and Tw) outside of a text object was wrong as Stefano Chizzolini pointed out: Some text related operations indeed are allowed outside text objects, namely the text state operations, cf. figure 9 from the PDF specification:
So while being less common, text state operations at page description level are completely ok.
After my incorrect attempt to explain the issue, the OP's own answer indicated that the
main stream of information in the PDF page has been corrupted. After it's end it had a copy of a past instance of it. This caused a partial text section without the starting command "BT" - which left a single "ET" without a "BT" in the end of the stream.
An ET without a prior BT indeed would be an error, and quite likely it would be accompanied by operations at the wrong level... Inspecting the stream content of that third page (the focused page of this issue), though, I could not find any unmatched ET. In the course of that inspection, though, I discovered that the content stream contains more than 2000 trailing 0 bytes! Adobe Reader seems not to be able to cope with these 0 bytes.
The bug the OP found, can explain the issue:
in the Buffer.java:clone() (line 217)
instead of line:
clone.append(data);
needs to be:
clone.append(data, 0, this.length);
Without this correction it clones the whole data buffer, and set the cloned Buffer's length to the data[].length. This is very problematic if the Buffer.length`` is smaller than the data[].length.
Trailing 0 bytes can be an effect of such a buffer copying bug.
Furthermore symptoms as found by the OP (After it's end it had a copy of a past instance of it) can also be the effect of such a bug. So I assume the OP found those symptoms on a different page, not page 3, but fixing the bug healed all symptoms.
How can I find what's wrong with it? is there a tool which tells you where does the error lie?
There are PDF syntax checkers, e.g. the Preflight tool included in Adobe Acrobat. but even that fails on your file.
So essentially you have to extract the page content (using a PDF browser, e.g. RUPS) and check manually with the PDF specification on the other screen.
the general post about debugging pdf might have been also helpful as rups / pdfstreamdump etc is mentioned there How do you debug PDF files?

Dynamically change an image in a Crystal Report at runtime

I'm using the Crystal Reports included with VisualStudio 2005. I would like to change the image that is displayed on the report at runtime ideally by building a path to the image file and then have that image displayed on the report.
Has anyone been able to accomplish this with this version of Crystal Reports?
At work we do this by pushing the image(s) into the report as fields of a datatable. It's not pretty, but it gets the job done. Of course, this solution requires that you push data into the reports via a DataSet. I've always felt this was a hack at best. I really wish that image parameters were a possibility with CR.
Edit: It's worth noting, if you are binding your crystal report to plain old objects you want to expose a byte[] property for the report to treat that as an image.
I finally reached a solution using the byte[] tip posted here by Josh.
This solution applies if you are using a plain old C# Object to populate your Crystal Reports (see http://www.aspfree.com/c/a/C-Sharp/Crystal-Reports-for-Visual-Studio-2005-in-CSharp/ for info on this approach).
In your C# class, insert the following code:
private static byte[] m_Bitmap = null;
public byte[] Bitmap
{
get
{
FileStream fs = new FileStream(bitmapPath, FileMode.Open);
BinaryReader br = new BinaryReader(fs);
int length = (int)br.BaseStream.Length;
m_Bitmap = new byte[length];
m_Bitmap = br.ReadBytes(length);
br.Close();
fs.Close();
return m_Bitmap;
}
}
Now, update your C# Object Mapping in CR using the "Verify Database" option. You should then see the Bitmap property as a CR field. Just drag it onto the form. It will be of type IBlobFieldObject. When you run, you should see your image.
[I have since found a solution using a byte array via a C# Object property - see separate Answer. Leaving this answer here for reference...]
Here's what I have seen suggested (but I tried and failed in both C#-2005 and C#-2008).
Choose a directory and place a BMP there (e.g., "C:\Temp\image.bmp").
From the CR-Designer a) Right-click->Insert->OLE Object... b) Select "Create from File" c) Check the "Link" checkbox d) Browse and pick the bmp defined in step 1 e) Click OK f) Place the image on the form.
Overwrite/update the image at runtime in your C# code. In theory, since you inserted a Link to an image file, it will be updated when the form is refreshed.
I had no luck with this approach. The image appears when I first design the form (step 2). But at runtime, the image does not update for me. From this point forward, things get really odd. It seems that CR caches some sort of image that just won't go away. I can delete the OLE object link in CR-Designer, but if I recreate it, I always get a black box the same size as the original image (even if I change the size of image.bmp).
You can also use a conditional formula to set an image's location. See Crystal Reports: Dynamic Images.
Try using a combination of using a parameter containing the path of the image and the tutorial on this page: http://www.idautomation.com/crystal/streaming_crystal.html
Then in step #8, use the parameter instead of a hard-coded path.
Another option that I've found useful is inserting the pictures you would like to use. Position the graphic accordingly, then right-click the graphic and go to Format Graphic > Common. Check the Suppress box, then click the formula button, shown as x-2. Once in the formula window, simply add the code for determining whether the graphic should be suppressed or not.
In my case, I was building one invoice template for multiple entities. In the formula window, I simply wrote COMPANY <> 1100 which meant that every time the invoice was run for a company other than 1100, the 1100 graphic would be suppressed.
Hopefully this makes life easier...
The current version of Crystal Reports (for Visual Studio 2012+) that I use with Visual Studio 2015 supports this function. Follow the following steps:
Insert a picture into your report. This will serve as your
placeholder.'
Right click your picture and choose Format Object
Select the Picture tab and the press the formula button
A formula window will open. Enter a formula that will find your pictures as links.
if({#isDonor}="1")
then "http://www.ny.org/images/aaf/picture1.jpg"
else "http://www.ny.org/images/aaf/picture2.jpg"
And you're done!
Just like Josh said.. You will have to push the image with a dataset. Or, put the image into a database table once and pull it in many times with a subreport.

Resources