Technical Article

Створення доступних переглядачів PDF з функцією Text-to-Speech у Delphi

Доступність більше не є додатковою функцією в сучасній розробці програмного забезпечення. Згідно з такими нормативними актами, як ADA (Закон про американців з інвалідністю) та Директива ЄС про доступність веб-сайтів, програмне забезпечення, що обробляє документи, повинно надавати допоміжні технології. Для переглядачів PDF це означає впровадження надійної функції перетворення тексту в мову (Text-to-Speech, TTS) та інтеграцію програм зчитування з екрана.

У цій статті ми розглянемо, як вилучати семантичні текстові потоки з PDF за допомогою PDFium у Delphi, а потім передавати цей текст у Windows Speech API (SAPI) для створення повністю доступного переглядача PDF.

Проблема вилучення тексту з PDF

PDF-файл за своєю суттю є полотном з інструкціями для малювання. Він за своєю природою не знає, що таке "абзац" або "стовпець"; він лише розміщує гліфи за певними координатами X/Y. Щоб прочитати документ вголос у логічному порядку, ваш аналізатор повинен відтворити порядок читання.

PDFium обробляє це за допомогою сімейства API FPDFText_*, яке аналізує просторові співвідношення гліфів для виведення зв'язних текстових потоків.

Крок 1: Вилучення тексту за допомогою PDFium

Перш ніж ми зможемо озвучити текст, ми повинні його вилучити. Наступний код Delphi демонструє, як ініціалізувати текстову сторінку та вилучити її вміст у стандартний рядок.

uses
  System.SysUtils, pdfium_lib;

function ExtractPageText(Doc: FPDF_DOCUMENT; PageIndex: Integer): string;
var
  Page: FPDF_PAGE;
  TextPage: FPDF_TEXTPAGE;
  CharCount: Integer;
  Buffer: array of WideChar;
begin
  Result := '';
  Page := FPDF_LoadPage(Doc, PageIndex);
  if Page = nil then Exit;
  
  try
    // Initialize the text extraction engine for this page
    TextPage := FPDFText_LoadPage(Page);
    if TextPage <> nil then
    begin
      try
        CharCount := FPDFText_CountChars(TextPage);
        if CharCount > 0 then
        begin
          SetLength(Buffer, CharCount + 1);
          // Extract the text into the wide string buffer
          FPDFText_GetText(TextPage, 0, CharCount, @Buffer[0]);
          Result := WideCharToString(@Buffer[0]);
        end;
      finally
        FPDFText_ClosePage(TextPage);
      end;
    end;
  finally
    FPDF_ClosePage(Page);
  end;
end;

Крок 2: Інтеграція Windows Speech API (SAPI)

Отримавши семантичний текст, ми можемо передати його до Windows Speech API. SAPI надає COM-інтерфейс SpVoice, який дозволяє здійснювати асинхронний синтез мовлення, вибір голосу та контроль швидкості мовлення.

uses
  System.Win.ComObj, Winapi.ActiveX;

const
  SVSFlagsAsync = 1;

procedure SpeakText(const TextToSpeak: string);
var
  SpVoice: OLEVariant;
begin
  CoInitialize(nil);
  try
    SpVoice := CreateOleObject('SAPI.SpVoice');
    // Speak asynchronously so the UI does not freeze
    SpVoice.Speak(TextToSpeak, SVSFlagsAsync);
  finally
    CoUninitialize;
  end;
end;

Крок 3: Синхронізація мовлення з виділенням тексту

Справді доступний переглядач не просто читає текст наосліп; він виділяє слова на екрані під час їх вимови. SAPI надає події (через точки підключення), які спрацьовують при досягненні межі слова.

Зіставивши індекс символу, повернутий подією межі слова SAPI, з індексом символу в PDFium за допомогою FPDFText_GetCharBox(), ви можете отримати обмежувальний прямокутник слова, що зараз вимовляється, і намалювати накладення виділення на полотні переглядача.

procedure HighlightWord(TextPage: FPDF_TEXTPAGE; CharIndex: Integer; CharCount: Integer);
var
  i: Integer;
  L, T, R, B: Double;
begin
  // Iterate through the characters of the spoken word
  for i := CharIndex to CharIndex + CharCount - 1 do
  begin
    // Get the physical bounding box on the PDF page
    FPDFText_GetCharBox(TextPage, i, @L, @R, @B, @T);
    // Transform PDF coordinates to screen coordinates and draw highlighting rect...
  end;
end;

Створення інклюзивного додатка

Поєднуючи вилучення просторового тексту з PDFium з мовним рушієм SAPI, розробники Delphi можуть створювати потужні інструменти для користувачів із вадами зору або тих, хто віддає перевагу сприйняттю на слух. Належне впровадження цих функцій гарантує, що ваш додаток відповідатиме суворим корпоративним і державним стандартам доступності.

Примітка: Інтегроване вилучення тексту та зіставлення координат повністю підтримуються компонентом PDFium Component.