Гіперпосилання PDF є URI анотаціями: прямокутник, що покриває певну область сторінки, який при натисканні вказує програмі перегляду відкрити URL. Анотація та текст під нею є абсолютно незалежними об'єктами. PrintHyperlink у HotPDF об'єднує їх в один виклик, малюючи текст та обчислюючи прямокутник анотації на основі метрик відмальованого тексту. Ця зручність приховує деталь, яку варто зрозуміти, перш ніж писати робочий код
Область натискання є окремою URI-анотацією, а текст лише визначає її геометрію, тому зміна шрифту або вирівнювання може змінити активний прямокутник навіть без зміни URL
Як працює PrintHyperlink
PrintHyperlink знаходиться у THPDFPage і приймає чотири аргументи: координати X та Y (в пунктах, початок координат зліва внизу, Y збільшується вгору), рядок мітки для малювання та цільовий URL. Внутрішньо він викликає TextOut поточним кольором гіперпосилання, а потім відразу обчислює прямокутник анотації з TextWidth та TextHeight при поточних метриках шрифту. Це означає, що шрифт і розмір мають бути встановлені до виклику, і вони не повинні змінюватися між малюванням мітки та розміщенням анотації, оскільки обидва дії виконуються в одному виклику
Колір за замовчуванням є clBlue. SetRGBHyperlinkColor змінює його лише для наступних викликів; він не оновлює заднім числом вже записані анотації. Якщо вам потрібні різні кольори для різних груп посилань на одній сторінці, викликайте SetRGBHyperlinkColor перед кожною групою та скидайте його після цього
Ось мінімальний документ, який створює три посилання двома різними кольорами:
procedure CreateLinkedReport(const FileName: string);
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := FileName;
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
// Default blue for informational links
Pdf.CurrentPage.TextOut(50, 750, 0, 'Reference links:');
Pdf.CurrentPage.PrintHyperlink(50, 720, 'Product page', 'https://www.loslab.com/en-us/pdf-library/delphi-pdf-component.html');
Pdf.CurrentPage.PrintHyperlink(50, 695, 'Online manual', 'https://www.loslab.com/en-us/pdf-library/delphi-pdf-component.html');
// Red for the action link
Pdf.CurrentPage.SetRGBHyperlinkColor(clRed);
Pdf.CurrentPage.PrintHyperlink(50, 660, 'Purchase license', 'https://www.loslab.com/en-us/buy-hotpdf-fastspring.html');
Pdf.CurrentPage.SetRGBHyperlinkColor(clBlue); // restore default
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Пастка координат
HotPDF використовує початок координат зліва внизу, при цьому Y зростає вгору, в пунктах (1/72 дюйма). Сторінка формату А4 має розмір 595 x 842 pt; сторінка формату US Letter - 612 x 792 pt. Координата Y=750 знаходиться поблизу верхнього краю сторінки А4, а Y=50 буде біля нижнього поля. Кожен, хто переходить від екранної графіки або HTML, припускає протилежне і розміщує перший рядок посилання прямо за межами видимої області
Прямокутник анотації, який обчислює PrintHyperlink, використовує ту саму систему координат. Якщо пізніше ви повернете сторінку, зміните її масштаб або розмір сторінки без перерахунку значень X/Y, видимий текст і клікабельний прямокутник розійдуться. Посилання "працює" в тому сенсі, що клік десь біля тексту запускає URL, але активна зона більше не збігається з тим, що бачить читач. Тестуйте на реальному розмірі сторінки та рівні масштабування, які ви постачаєте, а не лише на машині розробника при 100%
Один випадок, коли зміщення гарантовано: якщо ви викликаєте PrintHyperlink з координатами, придатними для сторінки А4, а потім перемикаєтесь на сторінку нестандартного вузького формату без налаштування значень X/Y, анотація може взагалі опинитися за межами сторінки. Об'єкт анотації все ще записується в PDF; більшість програм перегляду обрізають його тихо, тому посилання просто зникає без жодних помилок
Текст мітки проти цільового URL
Аргументи Text та Link незалежні. Ви можете намалювати "Download invoice PDF", тоді як ціллю є повний HTTPS URL з параметрами запиту. Цей поділ є навмисним; видима мітка має бути зручною для читання людиною, а URL може бути довгим або генеруватися динамічно
Проблеми виникають, коли міткою є сам URL, особливо довгий. Якщо URL візуально переноситься на два рядки, але прямокутник анотації був обчислений для однорядкового тексту, клікабельним є лише перший рядок. PrintHyperlink не обробляє багаторядковий потік; тримайте мітку достатньо короткою, щоб вона помістилася в одному рядку при поточному розмірі шрифту та ширині сторінки, або використовуйте коротку описову мітку з повним URL у якості цілі
Для документів, які будуть архівуватися або поширюватися без активного підключення до Інтернету, також врахуйте, чи повинен сам URL з'являтися у друкованому вигляді десь у тілі документа, а не лише як метадані анотації. Читач, який друкує PDF на папері, не отримує жодної користі від URI анотації
Повний приклад генерації документа
Наведений нижче шаблон показує більш реалістичний сценарій: генерація короткого звіту з розділом заголовка, основним текстом та нижнім рядком посилань, все з коду, а не з форми з полями TEdit:
procedure GenerateProductSheet(
const FileName, ProductName, ProductURL, SupportURL: string);
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := FileName;
Pdf.Compression := cmFlateDecode;
Pdf.BeginDoc;
// Header
Pdf.CurrentPage.SetFont('Arial', [fsBold], 16);
Pdf.CurrentPage.TextOut(50, 750, 0, WideString(ProductName));
// Body paragraph placeholder
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 710, 0, 'See the links below for full documentation.');
// Footer links
Pdf.CurrentPage.SetFont('Arial', [], 10);
Pdf.CurrentPage.TextOut(50, 80, 0, 'Links:');
Pdf.CurrentPage.PrintHyperlink(50, 60, 'Product page', ProductURL);
Pdf.CurrentPage.PrintHyperlink(200, 60, 'Support', SupportURL);
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Зауважте, що SetFont викликається перед кожною групою текстових викликів. Шрифт не зберігається при переході через AddPage, і якщо ви забудете встановити його перед PrintHyperlink на новій сторінці, прямокутник анотації буде обчислено відносно типових метрик сторінки, які можуть відрізнятися від ваших очікувань
Як обробка анотацій відрізняється в різних програмах перегляду
URI анотації PDF визначені в ISO 32000-1 §12.6.4.7, і кожна сумісна програма перегляду повинна їх дотримуватися. На практиці деякі аспекти поведінки відрізняються залежно від програми. Adobe Acrobat показує попередження системи безпеки під час першого кліку для URL-адрес, яких немає в списку довірених доменів; багато браузерів та легких програм для читання цього не роблять. Деякі корпоративні програми для перегляду PDF у суворо контрольованих середовищах повністю вимикають URI анотації згідно з політикою, тому клік нічого не робить, без видимої помилки. Мобільні PDF-додатки відрізняються тим, чи відкривають вони посилання всередині власного веб-переглядача додатка, чи передають це системному браузеру
Жодна з цих ситуацій не є помилкою, яку ви можете виправити зі сторони генерації; це рішення політики програм перегляду. Те, що ви можете зробити, це написати мітки посилань, які роблять URL видимим також у тілі документа, щоб читач у обмеженому середовищі все ще міг скопіювати адресу вручну. Анотація є зручністю; текст є запасним варіантом
Ще одна деталь, яку варто знати: URI анотації PDF за замовчуванням не мають візуального підкреслення. Підкреслення, яке ви бачите в більшості програм перегляду, малюється самою програмою на основі типу анотації, а не символом у потоці вмісту. Якщо вам потрібне фізичне підкреслення, яке витримає друк на неінтерактивному рендерері або перетворення PDF у зображення, намалюйте його явно за допомогою LineTo та Stroke на відповідному зміщенні Y нижче базової лінії тексту. Це окрема операція малювання, а не те, що PrintHyperlink робить за вас
Показаний тут API гіперпосилань є частиною HotPDF Component для Delphi та C++Builder