Increase the quality of the slide images in the exported pdf #18
Closes #18
Preview available at https://preview.excalideck.com/PR/46/
This feature is proving to be more difficult than anticipated.
The first approach I took was using Excalidraw's exportToSvg util to generate an svg to embed in the pdf. Implementing the svgSlideRenderer is actually quite easy (see gist), but it turns out it's not possible to embed svgs in pdfs! (At least not with the pdf-lib library Excalideck uses, but for what I've found, it's also not possible in general).
That leaves me with the following options:
- switch to the
pptxformat for the exported file, which allows embedding svgs - switch to the
htmlformat for the exported file, which allows embedding svgs - just generate higher-quality pngs
- generate the pdf from the svg (calling
pdf-lib'sdrawCircle,drawLine, etc) - avoid generating pdfs/pptx-s altogether, save files as
.excalideck(json) and just implement a presentation mode ( #29 )
Before going into the pros and cons of each option, I'll mention another problem that I noticed when - as a quick second approach - I tried to just generate higher-quality pngs: performance.
Generating higher quality pngs takes a significant amount of time, to the point that when clicking on the save button for the first time, several seconds pass before the save dialog opens (this is less of a problem for the subsequent save operations, since there's a UI element indicating that the save operation is in progress, and some steps of the operation are memoized). What's worse is that if the operation takes too much time (I didn't figure out the threshold), the save dialog never opens, because the browser "loses" the connection between the user action of clicking on the save button and the js call to the save-dialog-opening API, and therefore rejects the call as not authorized / not triggered by a user action.
In general this performance issue needs to be addressed whichever option is chosen. But let's go through the pros and cons of each option.
Option 1: switch to the pptx format for the exported file, which allows embedding svgs
Pros:
- slides are exported with the best possible quality
- pptx is a well-known format for presentations
Cons:
- it's more difficult to work with pptx. The PptxGenJs library seems quite good, but it only generates pptx files. Excalideck also needs to read them in order to extract the embedded metadata to restore from. Fortunately pptx files are actually just zip archives, so it might be possible to inject-into and read-from the archive a json file with the metadata
- embedding Excalidraw's fonts into the pptx might not be possible
- a
pdf -> pptxconversion tool of some sort would be needed for users with "old" Excalideck pdf files - I imagine generating slide svgs + the pptx file wouldn't be much quicker than generating pngs + the pdf file
Option 2: switch to the html format for the exported file, which allows embedding svgs
Pros:
- slides are exported with the best possible quality
- would lay the basis for other features (share url to presentation, etc)
Cons:
- html documents are "single page", so some additional js/css would be needed to display slides and allow moving between them
- customized-to-be-multi-page html files wouldn't be able to be opened/previewed well by other software, like email clients or macOS Quick Look
- embedding Excalidraw's fonts into a single
.htmlfile might be difficult - a
pdf -> hmtlconversion tool of some sort would be needed for users with "old" Excalideck pdf files
Option 3: just generate higher-quality pngs
Pros:
- performance issues aside, it's just a matter of increasing the export scale
Cons:
- quality can never be as good as with svgs
- text in the generated pdf is not selectable (not a regression from the current situation, but still a con to consider)
- the file size of the exported pdf would increase by
xtimes - it takes a long time to generate high-quality pngs
Option 4: generate the pdf from the svg (calling pdf-lib 's drawCircle, drawLine, etc)
Pros:
- slides are exported with the best possible quality
Cons:
- I think the conversion would be quite difficult and possibly a source of many rendering bugs
Option 5: avoid generating pdfs/pptx-s altogether, save files as .excalideck (json) and just implement a presentation mode
Pros:
- slides are presented with the best possible quality
- implements a much-requested feature
- simplifies file saving and loading
- improves performance of saving and loading to the point of avoiding the performance problem mentioned above (the only operation to do before opening the file-saving dialog is converting the deck js object into a
Blob, which is extremely fast no-matter the size of the deck) - would make it possible to identify Excalideck files (very good for many reasons, e.g. implementing double-click-to-open a file in Excalideck)
- would lay the basis for other features (export to html, share url to presentation, etc)
Cons:
- is a bigger feature to develop
- the possibility to export to pdf or other formats would still be desirable
- a
pdf -> excalideckconversion tool of some sort would be needed for users with "old" Excalideck pdf files -
.excalideckfiles wouldn't be able to be opened/previewed by other software, like email clients or macOS Quick Look
And here are some mockups for a "UI solution" to the performance issue mentioned in the previous comment.
Save modal
The first time the user clicks on the save icon, the following modal appears:

Generation completed
When the file-generation-process is completed, the modal transitions to this state:

Subsequent save operations
For subsequent save operations, the modal is not needed anymore, but the current UI could be updated to show a progress bar:

Having thought over the various options for a while, I think the simple Option 3: just generate higher-quality pngs is actually the best approach.
The pdf format is the most flexible of all: it's well understood by users, it can be viewed on any device and it can be previewed by other software, which greatly helps in managing the file (e.g. when you get an email with a pdf attached, you get a preview right in your email client and immediately understand what the file contains).
To solve the file-saving performance issue, the "UI solution" described above seems suitable.
Of course, choosing option 3 doesn't prevent the development of other features - like presentation mode, or exporting to different file formats. It just means that, for the time being, the Excalideck file-saving format will remain pdf.