Технічна стаття

Створення багатофункціонального засобу перегляду PDF за допомогою PDFium VCL у Delphi

Відтворення PDF часто є компромісом: ви або покладаєтеся на системні засоби перегляду, з якими важко інтегруватися, або використовуєте нативні VCL-компоненти, які можуть мати проблеми зі складними документами, або ж ліцензуєте дорогі комерційні механізми. PDFium — движок рендерингу з відкритим кодом, на якому працюють Google Chrome та Microsoft Edge — пропонує інший шлях: рендеринг промислового класу, який точно обробляє прозорість, складні шрифти та сучасні функції PDF

Хоча PDFium потужний, його C-подібний API не є природним для Delphi. Для відображення PDF на екрані вам потрібно керувати життєвим циклом об'єктів PDFium, обробляти багатонитковість для плавної прокрутки (smooth scrolling), перетворювати PDF-координати на пікселі екрана, а також виконувати рендеринг буферів PDFium у TBitmap Delphi. Компонент PDFium VCL від losLab долає цей розрив, огортаючи движок PDFium у нативні VCL-класи, надаючи вам інструменти для створення високоякісного засобу перегляду PDF (PDF viewer) безпосередньо у вашому застосунку Delphi за кілька хвилин

Налаштування компонента PDFium VCL

Перш ніж писати код, переконайтеся, що ви встановили компонент PDFium VCL. Пакет включає власне VCL-оболонку та необхідні бібліотеки PDFium (pdfium.dll для 32-бітних і 64-бітних версій). Після встановлення ви знайдете компоненти TLsPDFDocument та TLsPDFViewer на панелі інструментів (Tool Palette) Delphi

Крок 1: Завантаження документа

Основним класом керування даними є TLsPDFDocument. Він обробляє введення/виведення файлів, керування пам'яттю та розбір документів (document parsing) через движок PDFium. Щоб завантажити документ, ви можете прочитати його з файлу або з потоку. Завантаження з потоку корисне, якщо ваші PDF-файли зберігаються в базі даних або завантажуються через мережу

uses
  LsPDFDocument;

procedure TMainForm.LoadPDF(const FileName: string);
begin
  if LsPDFDocument1.Active then
    LsPDFDocument1.Active := False;
    
  // Load from a file path
  LsPDFDocument1.LoadFromFile(FileName);
  
  // Alternatively, load from a stream:
  // LsPDFDocument1.LoadFromStream(MyFileStream);
  
  // Provide password if the document is encrypted
  if LsPDFDocument1.IsEncrypted then
  begin
    if not LsPDFDocument1.Unlock('MyPassword') then
      ShowMessage('Incorrect password');
  end;
end;

Властивість Active стає True після успішного завантаження. На цьому етапі документ утримується в пам'яті PDFium, і ви можете отримати доступ до його властивостей, таких як LsPDFDocument1.PageCount та метадані (metadata)

Крок 2: Відображення PDF за допомогою TLsPDFViewer

TLsPDFViewer — це візуальний елемент керування VCL, який відображає сторінки PDF. Він розроблений для простоти: ви просто пов'язуєте його з об'єктом TLsPDFDocument. Засіб перегляду (viewer) автоматично обробляє смуги прокрутки, масштабування (zoom), кешування сторінок та відтворення (rendering) на екрані

procedure TMainForm.FormCreate(Sender: TObject);
begin
  // Link the viewer to the document
  LsPDFViewer1.Document := LsPDFDocument1;
  
  // Set display options
  LsPDFViewer1.PageColor := clWhite;
  LsPDFViewer1.BackgroundColor := clAppWorkspace;
  LsPDFViewer1.PageBorderColor := clGray;
  
  // Fit the first page to the width of the viewer
  LsPDFViewer1.FitWidth;
end;

Відтворення відбувається у фоновому потоці. Коли ви прокручуєте (scroll), засіб перегляду запитує в PDFium рендеринг видимих сторінок у внутрішні бітові мапи (bitmaps). Такий підхід гарантує, що ваш користувацький інтерфейс залишається чуйним, навіть під час рендерингу складних сторінок із великою кількістю векторної графіки. Засіб перегляду також реалізує безперервну прокрутку (continuous scrolling), що дозволяє плавно переходити між сторінками, як у професійному програмному забезпеченні для читання PDF

Крок 3: Впровадження масштабування та навігації

Для базового засобу перегляду PDF (PDF viewer) потрібні елементи керування масштабуванням (zoom controls) та навігація сторінками (page navigation). Компонент PDFium VCL робить їх реалізацію простою

// Zoom In
procedure TMainForm.btnZoomInClick(Sender: TObject);
begin
  LsPDFViewer1.Zoom := LsPDFViewer1.Zoom + 25; // Increase zoom by 25%
end;

// Zoom Out
procedure TMainForm.btnZoomOutClick(Sender: TObject);
begin
  if LsPDFViewer1.Zoom > 25 then
    LsPDFViewer1.Zoom := LsPDFViewer1.Zoom - 25;
end;

// Fit Modes
procedure TMainForm.btnFitWidthClick(Sender: TObject);
begin
  LsPDFViewer1.FitWidth;
end;

procedure TMainForm.btnFitPageClick(Sender: TObject);
begin
  LsPDFViewer1.FitPage;
end;

// Navigation
procedure TMainForm.btnNextPageClick(Sender: TObject);
begin
  if LsPDFViewer1.CurrentPage < LsPDFDocument1.PageCount - 1 then
    LsPDFViewer1.CurrentPage := LsPDFViewer1.CurrentPage + 1;
end;

Зверніть увагу, що у PDFium VCL, як і в базовому API PDFium, індекси сторінок (page indices) починаються з нуля. Сторінка 1 документа — це індекс 0. Переконайтеся, що ви враховуєте це при відображенні номерів сторінок у користувацькому інтерфейсі

Крок 4: Вилучення тексту (Text Extraction) та пошук (Searching)

Окрім візуалізації, PDFium VCL надає потужні можливості роботи з текстом. Вилучення тексту є точним і дотримується порядку читання (reading order). Ви можете витягти текст з певної сторінки або здійснювати пошук (search) за вказаними термінами та виділяти (highlight) їх

uses
  LsPDFTypes;

procedure TMainForm.SearchAndHighlight(const SearchTerm: string);
var
  SearchObj: TLsPDFTextSearch;
  RectList: TLsPDFRectList;
  I: Integer;
begin
  if not LsPDFDocument1.Active then Exit;
  
  // Clear previous highlights
  LsPDFViewer1.ClearHighlights;
  
  // Search on the current page (index 0-based)
  SearchObj := TLsPDFTextSearch.Create(LsPDFDocument1, LsPDFViewer1.CurrentPage, SearchTerm);
  try
    // Find all occurrences
    while SearchObj.FindNext do
    begin
      // A match might span multiple rectangles (e.g., across line breaks)
      RectList := SearchObj.GetMatchRects;
      for I := 0 to RectList.Count - 1 do
      begin
        // Add a highlight with a semi-transparent yellow color
        LsPDFViewer1.AddHighlight(LsPDFViewer1.CurrentPage, RectList[I], clYellow, 100);
      end;
    end;
  finally
    SearchObj.Free;
  end;
  
  // Force the viewer to repaint to show the highlights
  LsPDFViewer1.Invalidate;
end;

Вилучення тексту здійснюється за допомогою методу GetPageText класу документа (document class):

procedure TMainForm.ExtractTextToMemo;
var
  PageText: string;
begin
  if LsPDFDocument1.Active then
  begin
    // Extract text from the first page
    PageText := LsPDFDocument1.GetPageText(0);
    Memo1.Lines.Text := PageText;
  end;
end;

Крок 5: Друкування (Printing) засобами PDFium

Друкування (Printing) PDF-файлу може бути складним завданням, особливо коли йдеться про керування кольором та згладжування (anti-aliasing). PDFium VCL обробляє перетворення в контекст пристрою принтера (printer device context), забезпечуючи високу якість (high-fidelity) виводу

uses
  Printers;

procedure TMainForm.PrintDocument;
begin
  if not LsPDFDocument1.Active then Exit;
  
  if PrintDialog1.Execute then
  begin
    Printer.Title := 'PDFium VCL Print Job';
    Printer.BeginDoc;
    try
      // Print the current page to the printer canvas
      // The component automatically scales the PDF page to fit the printable area
      LsPDFDocument1.PrintPage(LsPDFViewer1.CurrentPage, Printer.Canvas.Handle, 
                               Printer.PageWidth, Printer.PageHeight);
    finally
      Printer.EndDoc;
    end;
  end;
end;

Цей підхід забезпечує точне відтворення (precise rendering) на папері. Якщо вам потрібно надрукувати весь документ, ви можете перебрати сторінки (loop through pages), викликаючи Printer.NewPage між ними

Висновок

Компонент PDFium VCL дозволяє швидко інтегрувати засіб перегляду PDF промислового класу у ваші застосунки Delphi. Оскільки він використовує той самий движок рендерингу (rendering engine), що й Google Chrome, ваші користувачі отримають швидке, точне та надійне відтворення PDF. Ми розглянули завантаження, відображення, масштабування, пошук і друкування, але компонент пропонує набагато більше, включаючи підтримку закладок (bookmarks support), обробку вкладень (attachment handling) та рендеринг сторінок (page rendering) у користувацькі бітові мапи (custom bitmaps) для безголової (headless) обробки