Technical Article

Izdelava dostopnih pregledovalnikov PDF z besedilom v govor (TTS) v Delphiju

Dostopnost ni več neobvezna funkcija v sodobnem razvoju programske opreme. Po predpisih, kot sta ADA (Zakon o Američanih invalidih) in Direktiva EU o spletni dostopnosti, mora programska oprema, ki obravnava dokumente, zagotavljati podporne tehnologije. Za pregledovalnike PDF to pomeni implementacijo robustne integracije besedila v govor (Text-to-Speech - TTS) in bralnikov zaslona.

V tem članku si bomo ogledali, kako s pomočjo mehanizma PDFium v Delphiju izluščiti semantične tokove besedila iz PDF dokumenta in nato to besedilo posredovati v Windows Speech API (SAPI) za izdelavo popolnoma dostopnega pregledovalnika PDF.

Izziv pri luščenju besedila iz PDF-jev

PDF je v osnovi platno z navodili za risanje. Sam po sebi ne ve, kaj je "odstavek" ali "stolpec"; le postavlja glife na specifične X/Y koordinate. Če želite prebrati dokument naglas v logičnem vrstnem redu, mora vaš razčlenjevalnik rekonstruirati vrstni red branja.

PDFium to obravnava prek družine API-jev FPDFText_*, ki analizira prostorske odnose glifov in izpiše koherentne tokove besedila.

1. korak: Luščenje besedila s PDFium

Preden lahko izgovorimo besedilo, ga moramo izluščiti. Naslednja Delphi koda prikazuje, kako inicializirati stran z besedilom in izluščiti njeno vsebino v standarden niz (string).

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. korak: Integracija z Windows Speech API (SAPI)

Ko imamo semantično besedilo, ga lahko posredujemo v Windows Speech API. SAPI zagotavlja COM vmesnik SpVoice, ki omogoča asinhrono sintezo govora, izbiro glasu in nadzor hitrosti govora.

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. korak: Sinhronizacija govora z označevanjem besedila

Resnično dostopen pregledovalnik besedila ne prebere zgolj slepo; izgovorjene besede hkrati označi (highlight) na zaslonu. SAPI zagotavlja dogodke (prek priključnih točk - connection points), ki se sprožijo, ko je dosežena meja besede.

S preslikavo indeksa znaka, ki ga vrne dogodek meje besede API-ja SAPI, nazaj v indeks znaka v PDFium z uporabo FPDFText_GetCharBox(), lahko pridobite omejevalni pravokotnik trenutno izgovorjene besede in narišete označevalno prekrivanje (highlight overlay) na platnu (canvas) vašega pregledovalnika.

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;

Izdelava vključujoče aplikacije

Z združevanjem prostorskega luščenja besedila, ki ga ponuja PDFium, in SAPI-jevega mehanizma za govor, lahko razvijalci v Delphiju ustvarijo zmogljiva orodja za slepe in slabovidne uporabnike ali tiste, ki se raje učijo slušno. Pravilna implementacija teh funkcij zagotavlja, da je vaša aplikacija v skladu s strogimi standardi dostopnosti za podjetja in državne ustanove.

Opomba: Integrirano luščenje besedila in preslikavo koordinat v celoti podpira PDFium Component.