Techninis straipsnis

„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

Jei tekstą nupiešėte patys, AddURILink leidžia virš jo uždėti spustelėjamą sritį, o AddGoToLink tvarko vidinę navigaciją dokumente. Šie metodai papildo PrintHyperlink, kai nuoroda turi apimti ne tik etiketę

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/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;

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

Kaip apeiti kelių eilučių apribojimą

PrintHyperlink apskaičiuoja vieną anotacijos stačiakampį, todėl kelių eilučių etiketės negalima patikimai naudoti kaip vienos nuorodos. Kiekvieną eilutę pieškite atskirai ir sukurkite atskirą anotaciją arba naudokite didesnę bendrą sritį, jei priimtina, kad spustelėjama būtų visa grupė

Spustelėjamos sritys virš savarankiškai nupiešto turinio su AddURILink

AddURILink tinka, kai nuorodos tekstą, piktogramą ar spalvotą foną jau nupiešėte kitais metodais. Perduokite tikslo URL ir tikslų stačiakampį puslapio koordinatėmis, kad anotacija sutaptų su matomu turiniu

Vidinė navigacija su AddGoToLink

AddGoToLink nukreipia į kitą to paties dokumento puslapį ir nekuria išorinės URI nuorodos. Tai patogus būdas kurti turinį, kryžmines nuorodas ar ankstesnio ir kito puslapio valdiklius, kai paskirties puslapis žinomas generavimo metu

Abiem metodams koordinates reikia skaičiuoti taip pat kaip ir piešiamam elementui: PDF pradžios taškas yra apačioje kairėje, o vertikali kryptis kyla į viršų. Jei puslapis pasuktas arba mastelis keičiamas, anotacijos stačiakampį transformuokite kartu su turiniu

Kelių eilučių tekstui kiekvienos eilutės plotį apskaičiuokite pagal tuo metu aktyvų šriftą, kad nuorodos sritis nesibaigtų per anksti

URI anotacija netikrina, ar URL yra pasiekiamas, todėl generavimo metu verta validuoti schemą ir tinkamai koduoti tikslo eilutę

Vidinė nuoroda nepriklauso nuo išorinio tinklo ryšio ir ypač tinka turiniui, priedams bei grįžimui į ilgų ataskaitų pradžią

Nuorodos stačiakampis turi būti tame pačiame koordinačių paviršiuje kaip ir puslapio turinys. Maišant ekrano ir PDF koordinates spustelėjama sritis pasislinks

Jei anotacija dedama virš vaizdo, jos ribas nustatykite pagal faktinį vaizdo dydį, įskaitant mastelį ir apkarpymą

Skirtingų spalvų grupėms nustatykite spalvą prieš kiekvieną grupę, nes vėlesnis nustatymas nekeičia jau įrašytų anotacijų

Peržiūros programos gali skirtingai rodyti anotacijos paryškinimą, tačiau paskirties veiksmą gauna iš PDF anotacijos žodyno

Generuojant dokumentą verta turėti pagalbinę funkciją, kuri vienu metu nupiešia etiketę, apskaičiuoja stačiakampį ir įrašo veiksmą

Prieš išleidimą patikrinkite nuorodas darbalaukio ir naršyklės peržiūros programose, nes jų paryškinimo stilius gali skirtis

Kiekvieną laužytos eilutės taikinį laikykite atskiru elementu, kad eilučių sritys nepersidengtų ir būtų lengvai testuojamos

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“