기술 문서

Delphi HotPDF Hello World: 첫 번째 PDF 프로그램

모든 PDF 라이브러리는 "hello world"를 제공하며, HotPDF의 "hello world"는 잠시 멈춰 살펴볼 만한 가치가 있습니다. 어떤 동작을 하는 가장 작은 프로그램이라도 이후 모든 문서에서 반복하게 될 두 가지 결정, 즉 어떤 글꼴을 설정할지와 페이지의 어느 위치에 텍스트를 배치할지를 강제하기 때문입니다. 이 두 가지를 제대로 맞추면 나머지 API는 그 응용에 불과합니다. 다음은 약 12개 언어로 독자에게 인사하는 단일 페이지를 작성하는 콘솔 프로그램의 전체 코드입니다:

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.

Delphi의 HotPDF 컴포넌트로 생성한 다국어 Hello World PDF

이것이 예제의 전부입니다. try/finally ... Free와 짝을 이루는 THotPDF.Create(nil)는 일반적인 Delphi 소유권 패턴이며, PDF라고 해서 달라지지 않습니다. 주목해야 할 점은 그 안에 있는 네 단계의 핵심 흐름입니다. 즉, 속성 설정, BeginDoc, 그리기, EndDoc 순서입니다. 이 순서는 서로 바꿀 수 없습니다

BeginDoc 전에 문서 속성 설정하기

BeginDoc은 HotPDF가 문서의 구조를 확정하는 순간이므로, 전체 파일에 영향을 미치는 모든 설정은 그 전에 완료해야 합니다. Compression := cmFlateDecode는 콘텐츠 스트림에 대해 FlateDecode를 켜서 콤팩트한 파일과 불필요하게 부풀려진 파일의 차이를 만듭니다. FontEmbedding := True는 파일 안에 그릴 때 사용한 글꼴을 패킹하여 Arial Unicode MS가 설치되지 않은 컴퓨터에서도 개발자 환경과 동일하게 보이게 합니다. 두 속성 중 하나라도 BeginDoc 이후에 할당하면 진행 중인 문서에 아무런 작업도 수행하지 않으며, 경고하는 오류도 발생하지 않습니다

SetFont를 호출한 뒤 TextOut을 호출하고 원점 주의하기

페이지를 처음 그릴 때 호출과 관련하여 누구나 두 가지 문제에 부딪힙니다. 첫 번째는 순서입니다. SetFont는 이에 의존하는 모든 TextOut 전에 실행되어야 하며, 현재 글꼴 설정은 페이지가 넘어가면 유지되지 않으므로 모든 AddPage 후에 반복해야 합니다. 두 번째는 좌표계입니다. TextOut은 왼쪽 상단이 아닌 페이지의 왼쪽 하단 모서리를 기준으로 측정하며, 위로 올라갈수록 Y 값이 증가합니다(단위: 포인트, 1/72 인치). 그렇기 때문에 여기 있는 줄들은 아래로 내려가며, 각 줄은 이전 줄보다 30포인트 아래에 위치합니다. 화면 그래픽 작업에 익숙한 사람이라면 반대로 생각하여 첫 번째 줄을 맨 아래쪽 바깥으로 곧장 써버리기 쉽습니다

하나의 글꼴, 다양한 문자

하나의 SetFont가 같은 페이지에서 라틴어, 키릴어, 일본어, 중국어를 모두 처리할 수 있는 이유는 서체 자체에 있습니다. Arial Unicode MS는 거의 모든 문자에 대한 글리프를 하나의 파일에 묶어놓았습니다. SetFont의 네 번째 인자는 Windows 문자 세트로, DEFAULT_CHARSET을 전달하면 모든 것을 하나의 레거시 코드 페이지로 고정하는 대신 시스템이 문자열마다 글리프를 선택할 수 있게 합니다. 하지만 이러한 편리함에는 두 가지 주의 사항이 따릅니다. HotPDF는 OS가 해당 이름을 해석한 결과를 포함시키므로 PDF를 생성하는 컴퓨터에 글꼴이 있어야 합니다. Arial Unicode MS가 누락된 경우 Windows는 조용히 대체 글꼴로 바꾸며 CJK 텍스트는 빈 상자로 나올 수 있습니다. 또한 모든 문자를 동등하게 지원하는 것은 아닙니다. 아랍어와 히브리어 같은 오른쪽에서 왼쪽으로 쓰는 문자나 복잡한 형태가 필요한 문자의 경우 RegisterUnicodeTTF로 불러오는 전용 글꼴과 오른쪽에서 왼쪽 텍스트 호출을 사용해야 하는데, 이는 별도의 주제입니다

실행하면 작업 디렉터리에 HelloWorld.pdf가 생성됩니다. 한 페이지 분량에 몇 줄의 다국어 텍스트가 압축되어 있고 글꼴이 포함된 파일입니다. 당연한 다음 단계는 해당 텍스트에 크기, 스타일, 회전을 적용하고 두 개 정 이상의 텍스트 블록을 의도적으로 배치하는 것인데, 이 두 가지는 TextOut 예제에서 다룹니다. 단순 텍스트가 아닌 선, 상자, 이미지를 그리고 싶을 때도 동일한 페이지 객체가 해당 호출을 제공합니다

여기에 표시된 TextOut, SetFont 및 문서 호출은 Delphi 및 C++Builder용 HotPDF Component의 일부입니다