I’ve been tasked with the creation of a PDF editing tool in a web browser. In short, I need to be able to add lines, rectangles, circles, texts and be able to measure distance. My only restriction is to use open-sourced and free existing libraries or do it myself.
I’ve looked into it, saw several paid apps that would do what I need (and much more) such as apryse, so I guess it’s possible (doesn’t mean it’s easy …).
I found several way to edit PDF in a webapp, with PDF.js, or an angular version (I used a lot of angular in the past years, so this was a good start for me).
After simply launching an app with the latter option, I quickly realized this was different from the paid apps I saw earlier. Which means, there’s a lot to do. Creating lines or rectangles doesn’t sound that hard, I’ve worked with SVG a lot, and I guess I can figure out something similar for PDFs. My main focus is the measuring tool.
Before even trying to measure anything, I wondered if I could find in the DOM a line I drew. Well, I can. For example, it looks like this :
<div data-editor-rotation="0" class="inkEditor draggable disabled" id="pdfjs_internal_editor_3"
tabindex="-1" data-l10n-id="pdfjs-ink" style="z-index: 4; left: 19.35%; top: 24.13%; width: 18.43%;
height: auto; aspect-ratio: 5.38 / 1;" aria-label="Éditeur de dessin">
<div class="resizers hidden">
<div class="resizer topLeft" data-resizer-name="topLeft" tabindex="-1"></div>
<div class="resizer topRight" data-resizer-name="topRight" tabindex="-1"></div>
<div class="resizer bottomRight" data-resizer-name="bottomRight" tabindex="-1"></div>
<div class="resizer bottomLeft" data-resizer-name="bottomLeft" tabindex="-1"></div>
</div>
<canvas height="74" width="393" class="inkEditorCanvas" data-l10n-id="pdfjs-ink-canvas"
aria-label="Image créée par l’utilisateur·trice" style="visibility: visible;"></canvas>
<div class="editToolbar hidden" role="toolbar"><div class="buttons">
<button class="delete" tabindex="0" data-l10n-id="pdfjs-editor-remove-ink-button"
title="Supprimer le dessin"></button>
</div>
</div>
With a bit of work I could probably modify the ID to something I handle to classify if it’s a line, a rectangle, whatever, so I should be able to get any drawn element in my typescript part (at least that doesn’t sound like a problem to me).
The thing is, now I have this DOM element, but there is no tool provided to measure anything. So I started looking into “how to measure a dom element in cm or in”. Well, I didn’t find anything easy there. Getting the size in px isn’t a problem. But then converting px in cm … is the real deal I guess.
I saw that apryse lets you draw a line of a known distance for example, which then makes it possible to measure anything. I wonder how that works, since you can change the zoom so it’s not a fixed quantity of px that equals to 1 cm.
Should I store the zoom value, px size of the known-sized line and calculate the scale each time zoom change ? Doesn’t sound efficient to me. It seems everything I found use canvas to draw on the PDF, but I’m not very familiar with it, I tried to search for canvas tools to measure distance, but didn’t find anything that seemed to fit my case.
I’ve read few things about DPI, but it seems it’s not easy to get it from the web browser, or at least I’m not sure it would work in any browser. Also I read several case where people got confused between screen ratio, DPI, etc. So I’m a bit confused about all that tbh, now that I’ve read many things and their opposite.
I used an angular module for the example, but anything in js would be fine with me, it is not a requirement, just something I’m confortable with.
I guess, to sumerize what I need is to understand how to efficiently get then store a scale value, so that I can measure anything on a given PDF doc. In every PDF I use, there are object with known size in cm, so I can draw a line that match the object size. But then what about the zoom ? I don’t want to recalculate the scale every time I zoom in or out.