Technical Article

Prieinamų PDF skaityklių su teksto skaitymo balsu (TTS) funkcija kūrimas „Delphi“ aplinkoje

Prieinamumas nebėra pasirenkama funkcija šiuolaikinėje programinės įrangos kūrimo aplinkoje. Pagal tokius reglamentus kaip ADA (Amerikiečių su negalia aktas) ir ES interneto prieinamumo direktyva, dokumentus apdorojanti programinė įranga privalo teikti pagalbines technologijas. PDF skaityklėms tai reiškia tvirtą teksto skaitymo balsu (TTS) ir ekrano skaitytuvų integraciją.

Šiame straipsnyje apžvelgsime, kaip „Delphi“ programoje išskirti semantinius teksto srautus iš PDF naudojant „PDFium“, o tada perduoti šį tekstą į „Windows Speech API“ (SAPI), siekiant sukurti visiškai prieinamą PDF skaityklę.

PDF teksto išskyrimo iššūkis

PDF iš esmės yra piešimo instrukcijų drobė. Formatas savaime „nežino“, kas yra „pastraipa“ ar „stulpelis“; jis tiesiog perkelia glifus į konkrečias X/Y koordinates. Norint logiška seka skaityti dokumentą garsiai, jūsų analizatorius turi atkurti skaitymo tvarką.

„PDFium“ tai sprendžia naudodamas FPDFText_* API šeimą, kuri analizuoja erdvinius glifų ryšius ir išveda nuoseklius teksto srautus.

1 žingsnis: teksto išskyrimas su „PDFium“

Prieš sakydami tekstą, privalome jį išskirti. Toliau pateiktas „Delphi“ kodas demonstruoja, kaip inicijuoti teksto puslapį ir išskirti jo turinį į standartinę eilutę.

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 žingsnis: „Windows Speech API“ (SAPI) integravimas

Gavę semantinį tekstą, galime jį perduoti į „Windows Speech API“. SAPI suteikia SpVoice COM sąsają, leidžiančią asinchroninę kalbos sintezę, balso pasirinkimą ir kalbėjimo greičio valdymą.

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 žingsnis: kalbos sinchronizavimas su paryškinimu

Tikrai prieinama skaityklė ne tik aklai skaito tekstą; ji taip pat paryškina žodžius ekrane juos tariant. SAPI suteikia įvykius (per ryšio taškus), kurie suveikia pasiekus žodžio ribą.

Susiedami simbolio indeksą, grąžintą iš SAPI žodžio ribos įvykio, su simbolio indeksu „PDFium“ variklyje per FPDFText_GetCharBox(), galite gauti šiuo metu tariamo žodžio ribojantį stačiakampį (angl. bounding rectangle) ir nupiešti paryškinimo perdengimą savo skaityklės drobėje.

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;

Įtraukios programos kūrimas

Derindami „PDFium“ erdvinį teksto išskyrimą su SAPI kalbos varikliu, „Delphi“ kūrėjai gali sukurti galingus įrankius silpnaregiams vartotojams arba tiems, kurie teikia pirmenybę mokymuisi klausantis. Tinkamas šių funkcijų įgyvendinimas užtikrina jūsų programos atitiktį griežtiems įmonių ir vyriausybių prieinamumo standartams.

Pastaba: integruotas teksto išskyrimas ir koordinačių susiejimas yra visiškai palaikomi „PDFium Component VCL“ komponente.