บทความเทคนิค

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.

ไฟล์ PDF Hello World หลายภาษาที่สร้างขึ้นโดย HotPDF component ใน Delphi

นั่นคือตัวอย่างทั้งหมด การจับคู่ THotPDF.Create(nil) กับ try/finally ... Free เป็นรูปแบบความเป็นเจ้าของ (ownership pattern) ตามปกติของ Delphi ซึ่งการใช้งาน PDF ก็ไม่ได้เปลี่ยนแปลงโครงสร้างนี้ สิ่งที่ควรให้ความสนใจคือโครงสร้างหลัก 4 ขั้นตอนที่อยู่ภายใน ได้แก่: การตั้งค่าคุณสมบัติ (properties), BeginDoc, การวาด (draw), และ EndDoc โดยลำดับเหล่านี้ไม่สามารถสลับที่กันได้

ตั้งค่าคุณสมบัติของเอกสารก่อน BeginDoc

BeginDoc คือจังหวะที่ HotPDF ยืนยันโครงสร้างของเอกสาร ดังนั้นสิ่งใดก็ตามที่ส่งผลต่อไฟล์ทั้งไฟล์จะต้องถูกตั้งค่าไว้ก่อนหน้านั้น Compression := cmFlateDecode จะเปิดการใช้งาน FlateDecode สำหรับสตรีมเนื้อหา ซึ่งสร้างความแตกต่างระหว่างไฟล์ที่มีขนาดกะทัดรัดกับไฟล์ที่มีขนาดใหญ่บวมเกินความจำเป็น FontEmbedding := True จะบรรจุฟอนต์ที่คุณใช้วาดลงในไฟล์ด้วย ดังนั้นเอกสารจะแสดงผลได้เหมือนกันบนเครื่องที่ไม่เคยติดตั้ง Arial Unicode MS เช่นเดียวกับเครื่องของคุณ หากคุณกำหนดค่าคุณสมบัติใดคุณสมบัติหนึ่งเหล่านี้หลังจากเรียกใช้ BeginDoc มันจะเพิกเฉยต่อเอกสารที่กำลังดำเนินการอยู่โดยไม่แสดงข้อผิดพลาดใดๆ เพื่อเตือนคุณเลย

SetFont, ตามด้วย TextOut, และระวังเรื่องจุดกำเนิดพิกัด

สองสิ่งเกี่ยวกับการเรียกใช้คำสั่งวาดมักจะทำให้ทุกคนสะดุดในการสร้างหน้าแรก สิ่งแรกคือลำดับ: SetFont จะต้องทำงานก่อน TextOut ใดๆ ที่ต้องใช้ฟอนต์นั้น และจะต้องเรียกซ้ำอีกครั้งหลังจาก AddPage เสมอ เนื่องจากฟอนต์ปัจจุบันจะไม่คงอยู่เมื่อมีการขึ้นหน้าใหม่ สิ่งที่สองคือระบบพิกัด TextOut จะวัดระยะจากมุมซ้ายล่างของหน้ากระดาษ ไม่ใช่มุมซ้ายบน โดยค่า Y จะเพิ่มขึ้นเมื่อคุณขยับขึ้นด้านบน มีหน่วยเป็นจุด (1/72 นิ้ว) นี่คือเหตุผลว่าทำไมบรรทัดในตัวอย่างนี้จึงไล่ระดับ ลงมา จาก 760 โดยแต่ละบรรทัดจะอยู่ต่ำกว่าบรรทัดก่อนหน้า 30 จุด ใครก็ตามที่คุ้นเคยกับการวาดกราฟิกบนหน้าจอจะคิดในทางตรงกันข้ามและเขียนบรรทัดแรกลงไปนอกขอบล่างของหน้ากระดาษเลย

ฟอนต์เดียว, รองรับหลายสคริปต์

เหตุผลที่ SetFont เพียงการเรียกใช้ครั้งเดียวสามารถนำเสนอทั้งอักษรละติน (Latin), ซิริลลิก (Cyrillic), ญี่ปุ่น, และจีน บนหน้าเดียวกันได้ก็คือตัวอักษรเอง: Arial Unicode MS ได้รวบรวม glyphs สำหรับสคริปต์เกือบทั้งหมดไว้ในไฟล์เดียว อาร์กิวเมนต์ที่สี่ของ SetFont คือชุดอักขระของ Windows และการส่ง DEFAULT_CHARSET จะช่วยให้ระบบสามารถเลือก glyphs ตามแต่ละสตริงได้ แทนที่จะผูกทุกอย่างไว้กับโค้ดเพจแบบเดิม อย่างไรก็ตาม มีข้อควรระวังสองประการที่มาพร้อมกับความสะดวกนี้ ฟอนต์นั้นจะต้องมีอยู่ในเครื่องที่สร้างไฟล์ PDF เนื่องจาก HotPDF จะฝังฟอนต์ใดๆ ก็ตามที่ OS แปลงชื่อมาให้; หากไม่มี Arial Unicode MS ระบบ Windows จะสลับไปใช้ฟอนต์ตัวแทนอย่างเงียบๆ และข้อความ CJK ของคุณอาจแสดงเป็นกล่องสี่เหลี่ยมว่างเปล่าได้ และมันก็ไม่ได้ครอบคลุมทุกสคริปต์อย่างเท่าเทียมกัน: สำหรับการเขียนจากขวาไปซ้ายอย่างเช่นภาษาอาหรับและฮีบรู หรือสิ่งใดๆ ที่ต้องการการจัดรูปแบบที่ซับซ้อน คุณจะต้องใช้ฟอนต์เฉพาะที่โหลดผ่าน RegisterUnicodeTTF ร่วมกับคำสั่งข้อความจากขวาไปซ้าย ซึ่งเป็นหัวข้อแยกต่างหาก

ลองเรียกใช้คำสั่ง แล้วคุณจะได้รับ HelloWorld.pdf ในไดเรกทอรีทำงานปัจจุบัน: เอกสารหนึ่งหน้าพร้อมข้อความหลายภาษาไม่กี่บรรทัด ซึ่งถูกบีบอัดและฝังฟอนต์ไว้เรียบร้อยแล้ว ขั้นตอนต่อไปที่ชัดเจนคือการกำหนดขนาด สไตล์ และการหมุนให้กับข้อความนั้น ตลอดจนการจัดวางข้อความมากกว่าหนึ่งบล็อกอย่างจงใจ ซึ่งทั้งสองเรื่องนี้ได้อธิบายไว้ใน ตัวอย่าง TextOut เมื่อคุณต้องการวาดเส้นสี่เหลี่ยม กล่อง และรูปภาพ นอกเหนือจากแค่ข้อความ อ็อบเจ็กต์ของหน้าเดียวกันก็รองรับการเรียกใช้คำสั่งเหล่านั้นด้วยเช่นกัน

คำสั่ง TextOut, SetFont, และเอกสารที่แสดงที่นี่เป็นส่วนหนึ่งของ HotPDF Component สำหรับ Delphi และ C++Builder