Technical Article

Création de visionneuses PDF accessibles avec synthèse vocale (Text-to-Speech) dans Delphi

L'accessibilité n'est plus une fonctionnalité optionnelle dans le développement logiciel moderne. En vertu de réglementations telles que l'ADA (Americans with Disabilities Act) et la directive européenne sur l'accessibilité du Web, les logiciels qui manipulent des documents doivent fournir des technologies d'assistance. Pour les visionneuses PDF, cela signifie l'implémentation d'une synthèse vocale (Text-to-Speech, ou TTS) robuste et l'intégration de lecteurs d'écran.

Dans cet article, nous allons voir comment extraire des flux de texte sémantique à partir d'un PDF à l'aide de PDFium dans Delphi, puis comment injecter ce texte dans l'API de synthèse vocale de Windows (SAPI) pour créer une visionneuse PDF entièrement accessible.

Le défi de l'extraction de texte PDF

Un PDF est fondamentalement une toile d'instructions de dessin. Il ne sait pas intrinsèquement ce qu'est un "paragraphe" ou une "colonne" ; il place simplement des glyphes à des coordonnées X/Y spécifiques. Pour lire un document à haute voix dans un ordre logique, votre analyseur doit reconstruire l'ordre de lecture.

PDFium gère cela via la famille d'API FPDFText_*, qui analyse les relations spatiales des glyphes pour générer des flux de texte cohérents.

Étape 1 : Extraction de texte avec PDFium

Avant de pouvoir lire le texte, nous devons l'extraire. Le code Delphi suivant montre comment initialiser une page de texte et extraire son contenu dans une chaîne standard.

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;

Étape 2 : Intégration de l'API vocale Windows (SAPI)

Une fois que nous avons le texte sémantique, nous pouvons le transmettre à l'API vocale de Windows. SAPI fournit l'interface COM SpVoice, qui permet la synthèse vocale asynchrone, la sélection de la voix et le contrôle du débit vocal.

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;

Étape 3 : Synchronisation de la parole avec la mise en surbrillance

Une visionneuse véritablement accessible ne se contente pas de lire le texte aveuglément ; elle met en surbrillance les mots à l'écran au fur et à mesure qu'ils sont prononcés. SAPI fournit des événements (via des points de connexion) qui se déclenchent lorsqu'une limite de mot est atteinte.

En mappant l'index de caractère renvoyé par l'événement de limite de mot SAPI avec l'index de caractère dans PDFium à l'aide de FPDFText_GetCharBox(), vous pouvez récupérer le rectangle de délimitation du mot actuellement prononcé et dessiner une surbrillance superposée sur le canevas de votre visionneuse.

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;

Créer une application inclusive

En combinant l'extraction de texte spatiale de PDFium avec le moteur vocal de SAPI, les développeurs Delphi peuvent créer des outils puissants pour les utilisateurs malvoyants ou ceux qui préfèrent l'apprentissage auditif. La mise en œuvre correcte de ces fonctionnalités garantit que votre application est conforme aux normes d'accessibilité strictes des entreprises et des gouvernements.

Remarque : L'extraction de texte intégrée et le mappage des coordonnées sont entièrement pris en charge par le composant VCL PDFium Component.

\n