Τεχνικό Άρθρο

Εισαγωγή και Εξαγωγή Σχολιασμών PDF ως XFDF στο Delphi

Το HotPDF εξάγει και εισάγει σχολιασμούς PDF ως XFDF μέσω δύο συναρτήσεων που ενεργούν στο τρέχον φορτωμένο έγγραφο, των ExportLoadedAnnotationsToXFDF και ImportLoadedAnnotationsFromXFDF. Το XFDF είναι η μορφή ανταλλαγής σχολιασμών XML που έχει τυποποιηθεί ως ISO 19444-1, και αυτό το ζεύγος επιτρέπει σε ένα πρόγραμμα Delphi ή C++Builder να παραδίδει τα σχόλιά του στο Acrobat ή σε ένα εργαλείο αναθεώρησης τρίτου μέρους και να λαμβάνει πίσω τα αποτελέσματα της σήμανσης, χωρίς να ξαναγράψει το περιεχόμενο της σελίδας στην οποία βρίσκονται οι σχολιασμοί

Φανταστείτε τις δύο κατευθύνσεις που επιλύει αυτό. Ένας αναθεωρητής ανοίγει την αναφορά που δημιουργήσατε στο Acrobat, τοποθετεί ένα κόκκινο βέλος σε ένα κακοευθυγραμμισμένο σχήμα, κυκλώνει ένα λάθος σύνολο και πληκτρολογεί μια σημείωση στο περιθώριο, και στη συνέχεια εξάγει τα σχόλια σε ένα μικρό αρχείο XFDF. Ή το αντίστροφο: το πρόγραμμά σας παράγει τις σημάνσεις μόνο του και πρέπει να τις στείλετε σε κάποιον του οποίου το εργαλείο δεν είναι το HotPDF. Σε κάθε περίπτωση, οι σχολιασμοί ταξιδεύουν ως XML που κατανοούν και οι δύο πλευρές, και οι σελίδες PDF παραμένουν byte προς byte όπως ήταν

Ποια είναι η διαφορά μεταξύ FDF και XFDF?

Τα FDF και XFDF μεταφέρουν το ίδιο ωφέλιμο φορτίο σε δύο διαφορετικές συντάξεις, και η διάκριση έχει σημασία τη στιγμή που αποφασίζετε ποιο αρχείο θα παραδώσετε σε ένα άλλο εργαλείο. Το FDF είναι η παλαιότερη μορφή Forms Data Format που ορίζεται στην ίδια την προδιαγραφή PDF: χρησιμοποιεί τη σύνταξη αντικειμένων PDF, οπότε ένα αρχείο FDF μοιάζει με ένα απλοποιημένο PDF και χρειάζεται έναν αναλυτή (parser) με γνώση PDF για να διαβαστεί. Το XFDF είναι η έκφραση XML των ίδιων δεδομένων, τυποποιημένη ανεξάρτητα ως ISO 19444-1, πράγμα που σημαίνει ότι οποιαδήποτε βιβλιοθήκη XML σε οποιαδήποτε πλατφόρμα μπορεί να το ανοίξει, να το συγκρίνει (diff) ή να το δημιουργήσει. Και οι δύο μορφές μπορούν να μεταφέρουν τιμές πεδίων φόρμας σε ένα δέντρο <fields>, το οποίο διέπει η ρήτρα 6.3 του ISO 19444-1, και σχολιασμούς σε ένα δέντρο <annots>. Το HotPDF χωρίζει αυτές τις ευθύνες, δρομολογώντας τα δεδομένα φόρμας μέσω του ExportLoadedFormToXFDF και κρατώντας το ExportLoadedAnnotationsToXFDF για την πλευρά <annots>. Όταν ανταλλάσσετε σχόλια με μια διαδικτυακή υπηρεσία, έναν διακομιστή αναθεώρησης Java ή ένα σενάριο, το XFDF είναι η μορφή που δεν αναγκάζει την άλλη πλευρά να ενσωματώσει έναν αναλυτή PDF

Πώς εξάγετε σχολιασμούς PDF ως XFDF στο Delphi;

Το HotPDF εξάγει σχολιασμούς διατρέχοντας κάθε σελίδα του φορτωμένου εγγράφου, εκπέμποντας ένα στοιχείο XFDF για κάθε υποστηριζόμενο σχολιασμό, και επιστρέφοντας τον αριθμό των σχολιασμών που γράφτηκαν. Φορτώστε πρώτα το PDF και, στη συνέχεια, καλέστε το ExportLoadedAnnotationsToXFDF με μια διαδρομή προορισμού. Το ακέραιο αποτέλεσμα είναι ο αριθμός των σχολιασμών που σειριοποιήθηκαν. Αποτέλεσμα ίσο με το μηδέν ή μικρότερο σημαίνει ότι δεν εξήχθη τίποτα και δεν γράφτηκε κανένα αρχείο, γεγονός που αποτελεί ένδειξη ότι το έγγραφο δεν περιείχε σχολιασμούς υποστηριζόμενου υποτύπου

var
  Pdf: THotPDF;
  Written: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('report-reviewed.pdf', '') > 0 then
    begin
      // Write one XFDF element per supported annotation on every page
      Written := Pdf.ExportLoadedAnnotationsToXFDF('comments.xfdf');
      if Written <= 0 then
        ShowMessage('No supported annotations were found');
    end;
  finally
    Pdf.Free;
  end;
end;

Το XFDF που προκύπτει είναι απλό, αναγνώσιμο XML. Το HotPDF γράφει μια ρίζα <xfdf> στον χώρο ονομάτων ISO 19444-1, ένα κοντέινερ <annots> και ένα θυγατρικό στοιχείο ανά σχολιασμό με τον δείκτη σελίδας με βάση το 0, το χρώμα και τη γεωμετρία του ως χαρακτηριστικά ή θυγατρικά στοιχεία. Μια γραμμή με κίτρινο γέμισμα και ανοιχτή αιχμή βέλους, δίπλα σε ένα γεμάτο πολύγωνο, σειριοποιείται ως εξής

<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/">
  <annots>
    <line page="0" start="72,700" end="220,700"
          color="#FF0000" interior-color="#FFFF00"
          head="OpenArrow" tail="None">
      <contents-richtext>Baseline looks off</contents-richtext>
    </line>
    <polygon page="0" color="#0000FF" interior-color="#CCE5FF">
      <vertices>72,120;180,120;180,200;72,200</vertices>
    </polygon>
  </annots>
</xfdf>

Πώς οι υποτύποι σχολιασμών αντιστοιχίζονται σε στοιχεία XFDF

Κάθε υποτύπος σχολιασμού αντιστοιχίζεται σε ένα συγκεκριμένο στοιχείο ISO 19444-1 με τη δική του σύμβαση γεωμετρίας, και το HotPDF ακολουθεί αυτές τις δομές αντί να επινοεί δικές του. Οι σχολιασμοί γραμμής φέρουν τα χαρακτηριστικά start και end που κρατούν τα δύο ζεύγη συντεταγμένων των άκρων, λαμβανόμενα απευθείας από τον πίνακα L του σχολιασμού, ενώ τα στυλ απόληξης γραμμής LE γίνονται χαρακτηριστικά head and tail. Οι σχολιασμοί πολυγώνου και πολυγραμμής μεταφέρουν τη λίστα σημείων τους σε ένα θυγατρικό στοιχείο <vertices> ως ζεύγη x,y διαχωρισμένα με ερωτηματικό, και όχι ως χαρακτηριστικό, επειδή ένα πρόγραμμα ανάγνωσης που αναμένει το θυγατρικό στοιχείο θα απορρίψει σιωπηλά τα σημεία που είναι κρυμμένα οπουδήποτε αλλού. Οι σχολιασμοί μελανιού (ink annotations), οι οποίοι μπορούν να κρατήσουν πολλές ξεχωριστές πινελιές, φωλιάζουν ένα στοιχείο <inklist> με ένα θυγατρικό στοιχείο <gesture> ανά πινελιά, έτσι ώστε μια υπογραφή πολλαπλών πινελιών να επιβιώνει στη διαδρομή ως διακριτές χειρονομίες και όχι ως ένα ενιαίο συγχωνευμένο σώμα

Το εμπλουτισμένο κείμενο, το χρώμα και το στυλ περιγράμματος επιβιώνουν παράλληλα με τη γεωμετρία. Το σώμα εμπλουτισμένου κειμένου μιας σημείωσης γράφεται ως θυγατρικό στοιχείο <contents-richtext>. Το εσωτερικό γέμισμα που αποθηκεύει το PDF στον πίνακα IC, το χρώμα μέσα σε έναν κύκλο, τετράγωνο, πολύγωνο ή αιχμή βέλους γραμμής και το γέμισμα ενός πλαισίου απόκρυψης, μεταφέρονται ως χαρακτηριστικό interior-color σε μορφή #RRGGBB. Το πλάτος περιγράμματος, το μοτίβο παύλας και ένα εφέ συννεφιασμένου περιγράμματος αντιστοιχίζονται στα χαρακτηριστικά width, dashes, style και intensity, οπότε μια επεξήγηση με συννεφιασμένο περίγραμμα εξακολουθεί να εμφανίζεται ως συννεφιασμένη στο άλλο άκρο. Το HotPDF διατηρεί επίσης το αναδυόμενο παράθυρο (popup) που είναι προσαρτημένο σε έναν σχολιασμό σήμανσης, εισάγοντας τη γεωμετρία του αναδυόμενου στοιχείου και την ανοιχτή ή κλειστή κατάστασή του στο λεξικό Popup του σχολιασμού, και μεταφέρει τις καταστάσεις ανοίγματος και αναθεώρησης των σχολιασμών κειμένου, ώστε ένα αναθεωρημένο έγγραφο να διατηρεί όχι μόνο τα σχήματά του αλλά και τα μεταδεδομένα ροής εργασίας στα οποία βασίζονται οι αναθεωρητές

Εισαγωγή του XFDF πίσω σε ένα φορτωμένο έγγραφο

Το HotPDF εισάγει XFDF αναλύοντας το XML, δημιουργώντας έναν νέο σχολιασμό για κάθε στοιχείο μέσω του NewLoadedAnnotation, προσαρτώντας τον στη σελίδα που ονομάζει το στοιχείο και επιστρέφοντας πόσους σχολιασμούς πρόσθεσε. Η ροή εργασίας είναι συμμετρική με την εξαγωγή: φορτώστε το βασικό PDF, καλέστε το ImportLoadedAnnotationsFromXFDF με το αρχείο του αναθεωρητή και, στη συνέχεια, αποθηκεύστε το φορτωμένο έγγραφο για να διατηρήσετε τις νέες σημάνσεις. Εάν το αρχείο λείπει ή το XML δεν αναλύεται, η συνάρτηση επιστρέφει μηδέν και το φορτωμένο έγγραφο παραμένει ανέπαφο

var
  Pdf: THotPDF;
  Added: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('report.pdf', '') > 0 then
    begin
      Added := Pdf.ImportLoadedAnnotationsFromXFDF('comments.xfdf');
      if Added > 0 then
        Pdf.SaveLoadedDocument('report-annotated.pdf');
    end;
  finally
    Pdf.Free;
  end;
end;

Επειδή κάθε στοιχείο XFDF ονομάζει τον δικό του δείκτη σελίδας, οι σχολιασμοί προσγειώνονται στις σελίδες για τις οποίες δημιουργήθηκαν, ακόμη και όταν εισάγετε πολλά αρχεία στη σειρά, γεγονός που καθιστά ασφαλή τη συλλογή σχολίων από περισσότερους από έναν αναθεωρητές στο ίδιο φορτωμένο έγγραφο πριν από μία μόνο αποθήκευση. Το παρακάτω παράδειγμα ενσωματώνει δύο αναθεωρητές σε ένα συγχωνευμένο αντίγραφο. Για τη δημιουργία και την επεξεργασία των ίδιων των αντικειμένων σχολιασμού στον κώδικα αντί για την ανταλλαγή τους ως αρχεία, δείτε πώς το HotPDF δημιουργεί και επεξεργάζεται αντικείμενα σχολιασμών PDF απευθείας από το Delphi

var
  Pdf: THotPDF;
  Total, I: Integer;
  Files: array[0..1] of string;
begin
  Files[0] := 'alice-comments.xfdf';
  Files[1] := 'bob-comments.xfdf';
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('master.pdf', '') > 0 then
    begin
      Total := 0;
      for I := Low(Files) to High(Files) do
        Inc(Total, Pdf.ImportLoadedAnnotationsFromXFDF(Files[I]));
      if Total > 0 then
        Pdf.SaveLoadedDocument('master-merged.pdf');
    end;
  finally
    Pdf.Free;
  end;
end;

Τι ολοκληρώνει καθαρά την κυκλική διαδρομή, και τι όχι

Το HotPDF πραγματοποιεί κυκλική διαδρομή για τους υποτύπους σχολιασμού που υποστηρίζει το ISO 19444-1, και παραλείπει σκόπιμα τους υπόλοιπους αντί να εκπέμπει κάτι που ένας αναγνώστης θα παρερμήνευε. Το υποστηριζόμενο σύνολο καλύπτει τους τύπους σήμανσης που κυριαρχούν στην πραγματική εργασία αναθεώρησης: σημειώσεις κειμένου, ελεύθερο κείμενο, γραμμή, τετράγωνο, κύκλος, πολύγωνο, πολυγραμμή, οι τέσσερις τύποι σήμανσης κειμένου (επισήμανση, υπογράμμιση, διαγραφή και κυματιστή υπογράμμιση), σφραγίδα, μελάνι και caret, συν συνημμένο αρχείο, ήχος, απόκρυψη (redaction) και σύνδεσμος, συνολικά δεκαοκτώ υποτύποι. Ένας σχολιασμός του οποίου ο υποτύπος βρίσκεται εκτός αυτής της λίστας παρακάμπτεται κατά την εξαγωγή, και επειδή παραλείπεται αντί να γραφτεί κενός, δεν αυξάνει τον αριθμό που επιστρέφει η συνάρτηση

Το εμπλουτισμένο κείμενο είναι η ειλικρινής προειδοποίηση. Το HotPDF διατηρεί το σώμα <contents-richtext>, οπότε το μορφοποιημένο κείμενο και τα απλά περιεχόμενα κάνουν το ταξίδι, αλλά το XFDF μεταφέρει τη σήμανση κειμένου και στυλ ενός σχολίου, και όχι μια αποδοθείσα ροή εμφάνισης. Έτσι, η εφαρμογή λήψης σχεδιάζει ξανά το αναδυόμενο παράθυρο με τις δικές της γραμματοσειρές και διάταξη, αντί να αναπαράγει τα ακριβή pixel του HotPDF. Αντιμετωπίστε την κυκλική διαδρομή ως πιστή στο περιεχόμενο και την πρόθεση, όχι στην απόδοση στην οθόνη μέχρι το επίπεδο του pixel. Εάν το μορφοποιημένο περιεχόμενό σας ζει σε δεδομένα φόρμας XFA αντί για ροές σχολιασμών, οι κανόνες διαφέρουν, και το πώς το HotPDF χειρίζεται XFA exData, εμπλουτισμένο κείμενο και υπερσυνδέσμους καλύπτει αυτή τη ξεχωριστή διαδρομή

Ο χειρισμός σε επίπεδο χαρακτήρων είναι πιο αυστηρός από ό,τι φαίνεται, κάτι που είναι ακριβώς αυτό που θέλετε. Το HotPDF εφαρμόζει τους κανόνες διαφυγής της ρήτρας 5.8.2 του ISO 19444-1 όταν γράφει κείμενο, κωδικοποιώντας τους χαρακτήρες που έχουν σημασία για το XML και τα bytes ελέγχου, έτσι ώστε ένα σχόλιο που περιέχει ένα ampersand, μια γωνιακή παρένθεση ή μια αλλαγή γραμμής να παράγει καλοσχηματισμένο XML που αποδέχεται οποιοσδήποτε συμβατός αναλυτής, και αντιστρέφει τους ίδιους κανόνες κατά την εισαγωγή. Αυτός είναι ο λόγος για τον οποίο μια σημείωση που επικολλάται από ένα υπολογιστικό φύλλο, μαζί με τα σημεία στίξης της, επιστρέφει ανέπαφη αντί να καταστρέψει το αρχείο

Η ανταλλαγή σχολιασμών είναι ένα μέρος αυτού που κάνει το API φορτωμένου εγγράφου, και συνδυάζεται με τα υπόλοιπα: εισαγωγή του XFDF ενός αναθεωρητή, προσαρμογή των σελίδων ή επεξεργασία των μεταδεδομένων του εγγράφου, επιπέδωση ή εκ νέου αδειοδότηση του αρχείου, και στη συνέχεια εξαγωγή ενός νέου XFDF για τον επόμενο γύρο. Όλα αυτά παρέχονται στο τυπικό HotPDF Component για Delphi και C++Builder, του οποίου η αναφορά τεκμηριώνει την πλήρη κάλυψη υποτύπων σχολιασμών και τις συνοδευτικές λειτουργίες XFDF δεδομένων φόρμας