Technical Article

Bygning af tilgængelige PDF-læsere med tekst-til-tale i Delphi

Tilgængelighed er ikke længere en valgfri funktion i moderne softwareudvikling. Under lovgivninger som ADA (Americans with Disabilities Act) og EU's direktiv om webtilgængelighed skal software, der håndterer dokumenter, levere understøttende teknologier. For PDF-læsere betyder det implementering af robust tekst-til-tale (TTS) og integration af skærmlæsere.

I denne artikel vil vi se på, hvordan man udtrækker semantiske tekst-streams fra en PDF ved hjælp af PDFium i Delphi, og derefter sender den tekst ind i Windows Speech API (SAPI) for at bygge en fuldt tilgængelig PDF-læser.

Udfordringen ved PDF-tekstudtrækning

En PDF er grundlæggende et lærred af tegningsinstruktioner. Den ved ikke i sig selv, hvad et "afsnit" eller en "kolonne" er; den placerer blot glyffer på specifikke X/Y-koordinater. For at læse et dokument højt i en logisk rækkefølge, skal din parser rekonstruere læserækkefølgen.

PDFium håndterer dette via FPDFText_* API-familien, som analyserer de rumlige relationer mellem glyffer for at udsende sammenhængende tekst-streams.

Trin 1: Udtrækning af tekst med PDFium

Før vi kan tale teksten, skal vi udtrække den. Følgende Delphi-kode demonstrerer, hvordan man initialiserer en tekstside og udtrækker dens indhold til en standard streng.

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;

Trin 2: Integration af Windows Speech API (SAPI)

Når vi har den semantiske tekst, kan vi sende den til Windows Speech API. SAPI leverer SpVoice COM-grænsefladen, som tillader asynkron talesyntese, stemmevalg og kontrol af talehastighed.

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;

Trin 3: Synkronisering af tale med fremhævning

En ægte tilgængelig læser læser ikke bare teksten blindt; den fremhæver ordene på skærmen, efterhånden som de bliver talt. SAPI leverer begivenheder (via connection points), der affyres, når en ordgrænse nås.

Ved at kortlægge det tegnindeks, der returneres af SAPI's ordgrænsebegivenhed, tilbage til tegnindekset i PDFium ved hjælp af FPDFText_GetCharBox(), kan du hente det afgrænsende rektangel for det aktuelt talte ord og tegne en fremhævningsoverlejring på dit læserlærred.

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;

Bygning af en inkluderende applikation

Ved at kombinere PDFiums rumlige tekstudtrækning med SAPIs talemotor kan Delphi-udviklere skabe kraftfulde værktøjer til synshandicappede brugere eller dem, der foretrækker auditiv læring. Korrekt implementering af disse funktioner sikrer, at din applikation overholder strenge tilgængelighedsstandarder for virksomheder og myndigheder.

Bemærk: Integreret tekstudtrækning og koordinatkortlægning understøttes fuldt ud af PDFium Component.