دسترسیپذیری دیگر یک ویژگی اختیاری در توسعه نرمافزار مدرن نیست. طبق مقرراتی مانند ADA (قانون آمریکاییهای دارای معلولیت) و بخشنامه دسترسی وب اتحادیه اروپا، نرمافزارهایی که اسناد را پردازش میکنند باید فناوریهای کمکی را ارائه دهند. برای نمایشگرهای PDF، این به معنای پیادهسازی قدرتمند تبدیل متن به گفتار (TTS) و ادغام صفحهخوان است.
در این مقاله، بررسی خواهیم کرد که چگونه میتوان جریانهای معنایی متن را از یک PDF با استفاده از PDFium در دلفی استخراج کرد و سپس آن متن را برای ساخت یک نمایشگر PDF کاملاً قابل دسترسی به Windows Speech API (SAPI) داد.
چالش استخراج متن PDF
یک فایل PDF اساساً یک بوم از دستورالعملهای نقاشی است. این فرمت ذاتاً نمیداند یک "پاراگراف" یا یک "ستون" چیست؛ بلکه صرفاً گلیفها (نویسهها) را در مختصات X/Y مشخصی قرار میدهد. برای خواندن یک سند با صدای بلند به ترتیب منطقی، تجزیهکننده شما باید ترتیب خواندن را بازسازی کند.
موتور PDFium این کار را از طریق خانواده API با نام FPDFText_* انجام میدهد که روابط مکانی گلیفها را برای خروجی جریانهای متنی منسجم تجزیه و تحلیل میکند.
مرحله ۱: استخراج متن با PDFium
قبل از اینکه بتوانیم متن را صحبت کنیم، باید آن را استخراج کنیم. کد دلفی زیر نحوه مقداردهی اولیه یک صفحه متنی و استخراج محتویات آن به یک رشته استاندارد را نشان میدهد.
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;مرحله ۲: ادغام رابط برنامهنویسی گفتار ویندوز (SAPI)
هنگامی که متن معنایی را در اختیار داریم، میتوانیم آن را به Windows Speech API ارسال کنیم. این رابط کاربری (SAPI) رابط COM به نام SpVoice را ارائه میدهد که امکان سنتز گفتار غیرهمگام (asynchronous)، انتخاب صدا و کنترل سرعت گفتار را فراهم میکند.
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;مرحله ۳: همگامسازی گفتار با برجستهسازی متن
یک نمایشگر کاملاً قابل دسترسی، متن را فقط به صورت کورکورانه نمیخواند؛ بلکه کلمات را در حین خوانده شدن روی صفحه نمایش برجسته میکند. رابط SAPI رویدادهایی (از طریق connection points) را فراهم میکند که هنگام رسیدن به مرز یک کلمه فعال میشوند.
با نگاشت (تطبیق) شاخص کاراکتر برگردانده شده توسط رویداد مرز کلمه 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، توسعهدهندگان دلفی میتوانند ابزارهای قدرتمندی برای کاربران کمبینا یا کسانی که یادگیری شنیداری را ترجیح میدهند ایجاد کنند. پیادهسازی صحیح این ویژگیها تضمین میکند که برنامه شما با استانداردهای دقیق دسترسیپذیری سازمانی و دولتی مطابقت دارد.
توجه: استخراج یکپارچه متن و نگاشت مختصات به طور کامل در کامپوننت PDFium Component VCL پشتیبانی میشود.