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

Delphi HotPDF Hello World: Το Πρώτο σας Πρόγραμμα PDF

Κάθε βιβλιοθήκη PDF παρέχει ένα "hello world", και αξίζει να σταθούμε σε αυτό του HotPDF, επειδή το μικρότερο πρόγραμμα που κάνει κάτι, σας αναγκάζει ήδη να πάρετε δύο αποφάσεις που θα επαναλαμβάνετε σε κάθε έγγραφο στη συνέχεια: ποια γραμματοσειρά να ορίσετε και πού στη σελίδα καταλήγει το κείμενο. Κατανοήστε αυτά τα δύο σωστά και το υπόλοιπο API είναι παραλλαγές στο ίδιο θέμα. Εδώ είναι ολόκληρο το πράγμα, ένα πρόγραμμα κονσόλας που γράφει μια μεμονωμένη σελίδα χαιρετώντας τον αναγνώστη σε σχεδόν δώδεκα γλώσσες:

program HelloWorld;

{$APPTYPE CONSOLE}

uses
  Winapi.Windows,   // for DEFAULT_CHARSET; on pre-XE2 Delphi use plain Windows
  HPDFDoc;          // HotPDF main unit

procedure CreateHelloWorld(const FileName: string);
var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := FileName;
    Pdf.Compression := cmFlateDecode;   // shrink the content streams
    Pdf.FontEmbedding := True;          // embed the face so it renders anywhere
    Pdf.BeginDoc;

    // One face covering many scripts. The 4th argument is the Windows charset;
    // DEFAULT_CHARSET lets the system pick glyphs per string.
    Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 14, DEFAULT_CHARSET);

    // TextOut measures from the BOTTOM-LEFT corner, in points, Y growing upward.
    Pdf.CurrentPage.TextOut(72, 760, 0, 'Hello, Delphi PDF world!');     // English
    Pdf.CurrentPage.TextOut(72, 730, 0, 'Hola, mundo Delphi PDF!');      // Spanish
    Pdf.CurrentPage.TextOut(72, 700, 0, 'Hallo, Delphi PDF Welt!');      // German
    Pdf.CurrentPage.TextOut(72, 670, 0, 'Bonjour, monde PDF Delphi!');   // French
    Pdf.CurrentPage.TextOut(72, 640, 0, 'Ciao, mondo Delphi PDF!');      // Italian
    Pdf.CurrentPage.TextOut(72, 610, 0, 'Olá, mundo Delphi PDF!');       // Portuguese
    Pdf.CurrentPage.TextOut(72, 580, 0, 'Здравствуйте, Delphi PDF мир!'); // Russian
    Pdf.CurrentPage.TextOut(72, 550, 0, 'こんにちは、Delphi PDFの世界!');    // Japanese
    Pdf.CurrentPage.TextOut(72, 520, 0, 'Merhaba, Delphi PDF dünyası!');  // Turkish
    Pdf.CurrentPage.TextOut(72, 490, 0, '你好,Delphi PDF世界');           // Chinese
    Pdf.CurrentPage.TextOut(72, 460, 0, '여보세요, Delphi PDF 세계!');      // Korean

    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

begin
  CreateHelloWorld('HelloWorld.pdf');
  Writeln('Wrote HelloWorld.pdf');
end.

Πολύγλωσσο (Multilingual) PDF Hello World που παρήχθη από το στοιχείο (component) HotPDF στο Delphi

Αυτό είναι ολόκληρο το παράδειγμα. Το THotPDF.Create(nil) σε συνδυασμό με το try/finally ... Free είναι το συνηθισμένο μοτίβο ιδιοκτησίας του Delphi, και το PDF δεν το αλλάζει. Αυτό που αξίζει προσοχής είναι η σπονδυλική στήλη τεσσάρων βημάτων στο εσωτερικό: ορισμός ιδιοτήτων, BeginDoc, σχεδίαση (draw), EndDoc. Η σειρά δεν είναι εναλλάξιμη

Ορισμός ιδιοτήτων εγγράφου πριν το BeginDoc

Το BeginDoc είναι η στιγμή που το HotPDF δεσμεύει τη δομή του εγγράφου, επομένως οτιδήποτε επηρεάζει ολόκληρο το αρχείο πρέπει να οριστεί πριν από αυτό. Το Compression := cmFlateDecode ενεργοποιεί το FlateDecode για τις ροές περιεχομένου (content streams), που είναι η διαφορά ανάμεσα σε ένα συμπαγές αρχείο και σε ένα άσκοπα διογκωμένο (bloated). Το FontEmbedding := True συσκευάζει τη γραμματοσειρά με την οποία σχεδιάζετε μέσα στο αρχείο, οπότε φαίνεται το ίδιο σε ένα μηχάνημα που δεν είχε ποτέ εγκατεστημένη την Arial Unicode MS όπως και στο δικό σας. Εκχωρήστε οποιοδήποτε από τα δύο μετά το BeginDoc και αθόρυβα δεν θα κάνει τίποτα στο έγγραφο που βρίσκεται ήδη σε εξέλιξη, χωρίς κανένα σφάλμα να σας προειδοποιήσει

SetFont, μετά TextOut, και προσέξτε την αρχή των αξόνων (origin)

Δύο πράγματα σχετικά με τις κλήσεις σχεδίασης πιάνουν τους πάντες απροετοίμαστους στην πρώτη τους σελίδα. Το πρώτο είναι η σειρά: το SetFont πρέπει να εκτελεστεί πριν από οποιοδήποτε TextOut που εξαρτάται από αυτό, και πρέπει να επαναληφθεί μετά από κάθε AddPage, επειδή η τρέχουσα γραμματοσειρά δεν επιβιώνει μετά από αλλαγή σελίδας (page break). Το δεύτερο είναι το σύστημα συντεταγμένων (coordinate system). Το TextOut μετράει από την κάτω αριστερή γωνία της σελίδας, όχι από την επάνω αριστερή, με το Υ να αυξάνεται καθώς μετακινείστε προς τα πάνω, σε σημεία (1/72 της ίντσας). Αυτός είναι ο λόγος για τον οποίο οι γραμμές εδώ προχωρούν προς τα κάτω από το 760, η καθεμία 30 σημεία κάτω από την προηγούμενη. Όποιος προέρχεται από γραφικά οθόνης υποθέτει το αντίθετο και γράφει την πρώτη γραμμή κατευθείαν έξω από το κάτω άκρο

Μία γραμματοσειρά, πολλές γραφές (scripts)

Ο λόγος για τον οποίο ένα απλό SetFont μπορεί να μεταφέρει Λατινικά, Κυριλλικά, Ιαπωνικά και Κινεζικά στην ίδια σελίδα είναι η ίδια η γραμματοσειρά: η Arial Unicode MS συγκεντρώνει (bundles) σύμβολα (glyphs) για σχεδόν κάθε γραφή σε ένα αρχείο. Το τέταρτο όρισμα (argument) στο SetFont είναι το σύνολο χαρακτήρων (character set) των Windows, και το πέρασμα (passing) του DEFAULT_CHARSET επιτρέπει στο σύστημα να επιλέξει σύμβολα ανά συμβολοσειρά (string) αντί να καρφιτσώσει τα πάντα σε μια παλιά κωδικοσελίδα (legacy code page). Δύο προειδοποιήσεις (caveats) συνοδεύουν αυτή την ευκολία. Η γραμματοσειρά πρέπει να υπάρχει στο μηχάνημα που κατασκευάζει το PDF, επειδή το HotPDF ενσωματώνει ό,τι επιλύει το λειτουργικό σύστημα για το όνομα· αν λείπει η Arial Unicode MS, τα Windows αντικαθιστούν αθόρυβα με ένα υποκατάστατο και το CJK κείμενό σας μπορεί να βγει ως άδεια κουτιά. Και δεν καλύπτει εξίσου κάθε γραφή: για γραφή από τα δεξιά προς τα αριστερά όπως τα Αραβικά και τα Εβραϊκά, ή οτιδήποτε χρειάζεται πολύπλοκη διαμόρφωση (complex shaping), φτάνετε σε μια ειδική γραμματοσειρά φορτωμένη με το RegisterUnicodeTTF και τις κλήσεις κειμένου από τα δεξιά προς τα αριστερά, το οποίο είναι ένα δικό του θέμα

Εκτελέστε το και παίρνετε το HelloWorld.pdf στον κατάλογο εργασίας (working directory): μία σελίδα, μερικές γραμμές πολύγλωσσου κειμένου, συμπιεσμένο, με ενσωματωμένη (embedded) τη γραμματοσειρά. Τα προφανή επόμενα βήματα είναι να δώσετε σε αυτό το κείμενο μέγεθος, στυλ και περιστροφή, και να τοποθετήσετε περισσότερα από ένα μπλοκ του σκόπιμα (deliberately), τα οποία και τα δύο το παράδειγμα TextOut τα αναλύει (works through). Όταν θέλετε να σχεδιάσετε κανόνες (rules), κουτιά και εικόνες αντί για απλό κείμενο, το ίδιο αντικείμενο σελίδας περιέχει και αυτές τις κλήσεις (calls)

Το TextOut, SetFont, και οι κλήσεις (calls) εγγράφου που εμφανίζονται εδώ αποτελούν μέρος του Στοιχείου Ελέγχου HotPDF για Delphi και C++Builder