Technical Article

„HotPDF“ „Delphi“ hipersaitai: patarimai dėl PrintHyperlink anotacijų

PDF hipersaitai (angl. hyperlinks) yra URI anotacijos: tai puslapio sritį dengiantis stačiakampis, kurį spustelėjus peržiūros programa atidaro URL adresą. Anotacija ir po ja esantis tekstas yra visiškai nepriklausomi objektai. HotPDF funkcija PrintHyperlink apjungia abu veiksmus į vieną iškvietimą: ji nupiešia tekstą ir apskaičiuoja anotacijos stačiakampį pagal atvaizduoto teksto matmenis. Už šio patogumo slepiasi detalė, kurią naudinga suprasti prieš rašant kodą gamybinei aplinkai.

Kaip veikia PrintHyperlink

Metodas PrintHyperlink yra klasėje THPDFPage ir priima keturis argumentus: X ir Y koordinates (taškais, pradinė koordinatė apačioje kairėje, Y didėja į viršų), piešiamą etiketės eilutę ir tikslo URL adresą. Vidinėje logikoje jis iškviečia TextOut su nustatyta hipersaito spalva, o po to iškart apskaičiuoja anotacijos stačiakampį pagal TextWidth ir TextHeight reikšmes, atsižvelgdamas į dabartinio šrifto matmenis. Tai reiškia, kad šriftas ir jo dydis turi būti nustatyti prieš iškvietimą ir negali keistis tarp etiketės piešimo ir anotacijos patalpinimo, nes abu veiksmai atliekami tame pačiame iškvietime.

Numatytoji spalva yra clBlue. SetRGBHyperlinkColor pakeičia ją tik būsimiems iškvietimams; ji neatnaujina jau įrašytų anotacijų spalvos atbuline data. Jei tame pačiame puslapyje skirtingoms saitų grupėms reikia skirtingų spalvų, iškvieskite SetRGBHyperlinkColor prieš kiekvieną grupę, o po to nustatykite spalvą iš naujo.

Štai minimalus dokumento pavyzdys, kuriame įrašomi trys hipersaitai su dviem skirtingomis spalvomis:

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/documentation.html');

    // Red for the action link
    Pdf.CurrentPage.SetRGBHyperlinkColor(clRed);
    Pdf.CurrentPage.PrintHyperlink(50, 660, 'Purchase license', 'https://www.loslab.com/en-us/order/');
    Pdf.CurrentPage.SetRGBHyperlinkColor(clBlue);  // restore default

    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

Koordinačių spąstai

HotPDF naudoja koordinačių sistemą su pradžios tašku apačioje kairėje, kur Y reikšmė didėja į viršų, matuojant taškais (1/72 colio). A4 puslapis yra 595 x 842 taškų dydžio; JAV Letter puslapis – 612 x 792 taškų. Y=750 reikšmė yra netoli A4 puslapio viršaus, o Y=50 būtų arti apatinės maržos. Kiekvienas, atėjęs iš ekrano grafikos ar HTML programavimo, daro priešingą prielaidą ir pirmąją saito eilutę nupiešia visiškai už matomos srities ribų.

Anotacijos stačiakampis, kurį apskaičiuoja PrintHyperlink, naudoja tą pačią koordinačių sistemą. Jei vėliau pasuksite puslapį, pakeisite jo mastelį ar puslapio dydį neperskaičiavę X/Y reikšmių, matomas tekstas ir spustelėjamas stačiakampis išsiskirs. Saitas teoriškai veiks ta prasme, kad spustelėjus kur nors netoli teksto bus atidarytas URL, tačiau spustelėjimo sritis nebeatitiks to, ką mato skaitytojas. Atlikite testavimą su realiu puslapio dydžiu ir masteliu, o ne tik kūrimo mašinoje su 100% masteliu.

Vienas iš atvejų, kai nesutapimas yra garantuotas: jei iškvieskite PrintHyperlink su A4 puslapiui tinkamomis koordinatėmis, o po to pereisite prie pasirinktinio siauro formato puslapio nepritaikę X/Y reikšmių, anotacija gali atsidurti visiškai už puslapio ribų. Anotacijos objektas vis tiek bus įrašytas į PDF failą; dauguma peržiūros programų jį tiesiog nukirps, todėl saitas tiesiog išnyks be jokio klaidos pranešimo.

Etiketės tekstas prieš URL adresą

Argumentai Text ir Link yra nepriklausomi. Galite nupiešti etiketę „Atsisiųsti sąskaitą faktūrą PDF“, o tikslo adresas gali būti pilnas HTTPS URL su užklausos parametrais. Šis atskyrimas yra apgalvotas; matoma etiketė turi būti suprantama žmogui, o pats URL gali būti ilgas arba sugeneruotas dinamiškai.

Problemos kyla kai pati etiketė yra neapdorotas URL adresas, ypač ilgas. Jei URL vizualiai persikelia į dvi eilutes, tačiau anotacijos stačiakampis buvo apskaičiuotas vienai eilutei, spustelėti bus galima tik pirmąją eilutę. PrintHyperlink neapdoroja kelių eilučių teksto; laikykite etiketę pakankamai trumpą, kad ji tilptų vienoje eilutėje su dabartiniu šrifto dydžiu ir puslapio pločiu, arba naudokite trumpą aprašomąją etiketę su pilnu URL adresu kaip tikslu.

Dokumentuose, kurie bus archyvuojami arba platinami be aktyvaus interneto ryšio, taip pat apsvarstykite, ar pats URL adresas neturėtų būti atspausdintas kur nors dokumento tekste, o ne tik kaip anotacijos metaduomenys. Skaitytojas, atspausdinęs PDF failą ant popieriaus, iš URI anotacijos negaus jokios naudos.

Pilnas dokumento generavimo pavyzdys

Žemiau pateiktas pavyzdys rodo realesnį scenarijų: trumpos ataskaitos su antraštės skiltimi, pagrindiniu tekstu ir hipersaitų eilute puslapio apačioje generavimas tiesiogiai iš kodo, nenaudojant formos su TEdit laukeliais:

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;

Atkreipkite dėmesį, kad SetFont iškviečiamas prieš kiekvieną teksto iškvietimų grupę. Šriftas neišlieka sukūrus naują puslapį per AddPage, ir jei pamiršite jį nustatyti prieš PrintHyperlink naujame puslapyje, anotacijos stačiakampis bude apskaičiuojamas pagal numatytuosius puslapio šrifto matmenis, kurie gali skirtis nuo jūsų planuotų.

Anotacijų apdorojimo skirtumai skirtingose peržiūros programose

PDF URI anotacijos yra apibrėžtos ISO 32000-1 §12.6.4.7 standarte ir kiekviena jį atitinkanti peržiūros programa turėtų jų laikytis. Praktikoje kai kurios elgsenos skiriasi priklausomai nuo programos. „Adobe Acrobat“ parodo saugumo įspėjimą pirmą kartą spustelėjus URL adresus, kurie nėra įtraukti į patikimų domenų sąrašą; daugelis naršyklių ir lengvų peržiūros programų to nedaro. Kai kurios įmonių PDF peržiūros programos apribotose aplinkose dėl saugumo politikos visiškai išjungia URI anotacijas, zodžiu, spustelėjimas nieko nedaro ir nerodo jokios klaidos. Mobiliosios PDF programos taip pat skiriasi tuo, ar atidaro nuorodas pačioje programoje, ar perduoda jas sisteminei naršyklei.

Nei vieno iš šių atvejų nėra klaida, kurią galėtumėte ištaisyti generavimo pusėje; tai yra peržiūros programų politikos sprendimai. Ką galite padaryti, tai sukurti nuorodų etiketes taip, kad pats URL būtų matomas ir dokumento tekste – taip skaitytojas apribotoje aplinkoje vis tiek galės nukopijuoti adresą rankiniu būdu. Anotacija yra patogumas, o tekstas – atsarginis variantas.

Dar viena detalė, kurią verta žinoti: PDF URI anotacijos pagal numatytuosius nustatymus neturi jokio vizualinio pabraukimo. Pabraukimas, kurį matote daugelyje peržiūros programų, yra nupiešiamas pačios peržiūros programos pagal anotacijos tipą, o ne pačiame turinio sraute. Jei jums reikia fizinio pabraukimo, kuris išliktų spausdinant neinteraktyviu atvaizdavimo įrengniu arba konvertuojant PDF į vaizdą, nupieškite jį patys naudodami LineTo ir Stroke su atitinkamu Y poslinkiu žemiau teksto bazinės linijos. Tai yra atskira braižymo operacija, kurios PrintHyperlink neatlieka už jus.

Čia parodytas hipersaitų API yra HotPDF komponento dalis, skirta „Delphi“ ir „C++Builder“.