Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compressed PDF not displayd correctly in OSX preview #2904

Closed
markotaht opened this issue Sep 8, 2020 · 19 comments
Closed

compressed PDF not displayd correctly in OSX preview #2904

markotaht opened this issue Sep 8, 2020 · 19 comments

Comments

@markotaht
Copy link
Contributor

markotaht commented Sep 8, 2020

Using the jsPDF to construct a PDF file and for reduced size it is compressed. Works fine in most places but when opened in OSX preview, the text is all jumbled up.

When validating the PDF with: https://www.pdf-online.com/osa/validate.aspx i get
`

Compliance pdf1.4
Result Document does not conform to PDF/A.
Details Validating file "cert(2).pdf" for conformance level pdf1.4Error in Flate stream: data error.The document does not conform to the requested standard.The document doesn't conform to the PDF reference (missing required entries, wrong value types, etc.).The document does not conform to the PDF 1.4 standard.Done.

`

I used //@ts-ignore doc.__private__.setPdfVersion("1.4"); in hopes of maybe resolving the issue. But it seems its not the issue with PDF version but with the compression algorithm. Is there a workaround for this issue?

I have worked with mozillas PDF.js libary and there i also had to implement compression. We needed to modify/extend the PDF.js libary to accomodate our signing logic. There i used pako libary to deflate a data stream. Maybe look into what pako has done? https://github.com/nodeca/pako

@HackbrettXXX
Copy link
Collaborator

Duplicate of #2743.

If you already have experience PDF compression. Could you maybe prepare a pull request with the fix? That would be awesome!

@markotaht
Copy link
Contributor Author

Well... i can try. Probably gona take a while until i understand the structure of this project and find everything i need to change.

@HackbrettXXX
Copy link
Collaborator

Thanks. If you need a pointer let me know ;)

@markotaht
Copy link
Contributor Author

@HackbrettXXX Can you make a quick overview on how the current Deflater.js is used? I keep finding pits and pieces all around the place, and it makes it rather difficult to root it out and supstitute it :D.

@HackbrettXXX
Copy link
Collaborator

Of course:

  • If the user passes compress: true to jsPDF, "FlateEncode" is added to the filter chain.
  • When any jsPDF function writes a PDF stream (putStream in jspdf.js), it is processed by the filter chain
  • putStream calls processDataByFilters, which then calls FlateEncode (filters.js)
  • This is where the "magic" happens and the Deflater is used

The deflater is also used in the png_support (compressBytes) file when compressing PNG images.

The deflater accepts uncompressed Uint8Arrays and returns compressed Uint8Arrays. I'm not sure if the bug is inside Deflater.js or in the FlateEncode function. Maybe even in the checksum calculated in adler32cs.js.

@markotaht
Copy link
Contributor Author

markotaht commented Sep 15, 2020

@HackbrettXXX Did some testing. I commented out adler and deflater and used pako and different combinations. It seems deflater + adler dont work together.

@markotaht
Copy link
Contributor Author

@HackbrettXXX Could you instruct me on how to build the package in such a way that it would work, if i have done npm install pako. It seems that the rollup kinda wants something but i cant quite put my finger on it.

@HackbrettXXX
Copy link
Collaborator

Sorry for the delayed response. If you're importing pako from node_modules, you probably need to add the resolve and commonjs plugins to the rollup config (like in the umdPolyfills entry). If this is not the issue I need a more detailed description of what goes wrong ;)

@markotaht
Copy link
Contributor Author

markotaht commented Sep 24, 2020

So i did npm install pako. Next i created a file under libs called pako.js with content

var pako;

(function() {
  pako = require("pako");
})();

export { pako};

Now im importing it by import { pako } from '../libs/pako.js';
I didnt know hwere exactly to but the pako so

"peerDependencies": {
    "pako": "^1.0.11"
  },

In rollup do i just input the libs file and output the rolledUp file and in between i use resolve and commonjs ?

@HackbrettXXX
Copy link
Collaborator

Just change the plugins config in rollup.config.js to this for the umd, node, and es entry points.

  plugins: [
    resolve(),
    commonjs(),
    RollupPluginPreprocess({ context: { MODULE_FORMAT: "cjs" } }),
    replaceVersion(),
    licenseBanner()
  ]

@markotaht
Copy link
Contributor Author

Ok build does not give errors. Any good way to test if the built version works?
Also i dint touch the PNG part. There is some weird logic that i dont understand. Seems like some length is added twice

 var a = deflate.append(bytes);
    var cBytes = deflate.flush();

    var len = header.length + a.length + cBytes.length;

@HackbrettXXX
Copy link
Collaborator

Well, create some PDFs with compression on and see if they open fine in the OSX PDF preview. You should probably also test PDFs with some binary data such as images or fonts.

@markotaht
Copy link
Contributor Author

Seems to work fine. But new issue, but harder one. I have a link in the PDF. Visually looks fine, but when clicked on in OSX preveiw # gets replaced with %23. Any ideas?

@HackbrettXXX
Copy link
Collaborator

"%23" is "#" URI encoded, so this is correct. If you open the link in a browser it should work. Or is the issue that the # that separates URI fragments is encoded, as well? Then it's probably an issue of encodeURI vs. encodeURIComponent.

@markotaht
Copy link
Contributor Author

Nevermind # to %23 is a macOS issue.

Anyways... i think im done... how do i push it up or something? I cant push as i get acces denied :D.

@HackbrettXXX
Copy link
Collaborator

You need to fork the repo, then create a pull request.

@markotaht
Copy link
Contributor Author

Should be ok. But this is my first fork ever :D so please check if i did everything correctly :D

@wesleymostien
Copy link

a workaround (for garbled text when using compression) I have found is using filters: ['ASCIIHexEncode', 'FlateEncode']

when creating a new jsPDF instance

new jsPDF({
	compress: true,
	filters: ['ASCIIHexEncode', 'FlateEncode'],
	format: [widthPdf, heightPdf],
	putOnlyUsedFonts: true,
	unit: 'px',
})

@HackbrettXXX
Copy link
Collaborator

Fixed in #2944.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants