PDF ne pozna pojma spremenljive pisave. Pisava, vdelana v datoteko PDF, je fiksen nabor obrisov s fiksnimi metrikami, zato je treba spremenljivo pisavo, preden gre v dokument, skrčiti na eno statično instanco. HotPDF to instanciranje izvede interno: preverite osi spremenljive pisave, izberete koordinate, na primer debelino 620 ali širino 87,5, knjižnica pa te vrednosti vpeče v popoln, samostojen program pisave, ki ga lahko upodobi vsak skladen bralnik PDF
Razlog, zakaj je to pomembno, je praktičen in ne teoretičen. Livarne pisav vse pogosteje dobavljajo eno samo spremenljivo datoteko namesto ducata statičnih debelin, oblikovalske ekipe pa izbirajo vrednosti, ki jih nobena poimenovana instanca ne ponuja. Brez instanciranja se generator poročil bodisi vrne na privzeto instanco, kar zavrže oblikovalsko odločitev, bodisi vdela celotno spremenljivo pisavo in upa, da bo pregledovalnik upošteval koordinate osi, o katerih nima nobenega načina, da bi zanje sploh vedel, kar od bralnika ni zahtevano
Kaj mora instanciranje dejansko zgraditi na novo?
Spremenljiva pisava OpenType za vsak znak shrani en privzeti obris ter nabor delt, indeksiranih po položaju v oblikovalskem prostoru. Uveljavitev koordinate osi ni stvar zapisa števila v glavo; pomeni sprehod skozi tabelo gvar, interpolacijo delt za zahtevani položaj, premikanje točk in nato ponoven izračun vsega, kar je bilo izpeljano iz teh točk. HotPDF na novo zgradi obrise znakov, dolgo tabelo loca, celotne vodoravne in navpične metrike, globalni omejevalni okvir pisave in prilagoditev kontrolne vsote sfnt
Enako pomembno je, kaj se odstrani. Statična instanca ne sme obdržati fvar, avar, gvar, HVAR, VVAR, MVAR, STAT ali cvar, prav tako mora izginiti zastarel DSIG, saj podpisani bajti ne obstajajo več. Če katera koli od teh ostane, nastane pisava, ki trdi, da je spremenljiva, hkrati pa nosi obrise, ki so že bili premaknjeni, bralniki, ki variacije dejansko uveljavljajo, pa jih bodo nato uveljavili še drugič
Fantomske točke in past dvojne uveljavitve
Najbolj prefinjeno pravilo v celotnem postopku zadeva metrike. V gvar število točk za znak zajema obrisne točke oziroma komponentne točke za sestavljen znak, plus štiri fantomske točke, ki kodirajo levi bočni razmik, pomik in njune navpične ustreznice. Tudi te fantomske točke so predmet delt
Ko ima torej pisava tabelo gvar, HotPDF izpelje vodoravne in navpične metrike iz interpoliranih fantomskih točk in ne uveljavi dodatno še HVAR ali VVAR. Uveljavitev obojega je klasična napaka: ista variacija se uveljavi dvakrat, vsak pomik pa pride ven nekoliko preširok, kar se pokaže kot besedilo, ki se v poravnani vrstici postopoma zamika v desno. Šele kadar pisava nima gvar, knjižnica shrambo metričnih variacij vpeče neposredno v hmtx ali vmtx
Dve nadaljnji podrobnosti ohranjata geometrijo pravilno. Fantomske točke nikoli ne sodelujejo pri interpolaciji obrisa, zato se točke, ki za enostaven znak niso izrecno navedene, izpeljejo z IUP po posameznem obrisu, pri čemer so fantomske točke izključene. Sestavljenim znakom se delte uveljavijo na komponentnih odmikih, ki uporabljajo parametre XY, nato pa se meje podrejenih elementov rekurzivno ponovno izračunajo. Ta rekurzija je omejena po globini in preverjena glede ciklov, ker bi se sicer sovražen ali zgolj pokvarjen graf komponent lahko rekurzivno klical v nedogled
Pregled oblikovalskega prostora, preden izberete
Prvi klic v vsakem poteku dela z instanciranjem je InspectVariableFont, ki poroča o oseh in poimenovanih instancah, ki jih je definirala livarna. Zapisi osi nosijo štiribajtno oznako, minimalno, privzeto in maksimalno vrednost, zastavice in ID imena; poimenovane instance nosijo ID imena poddružine, zastavice, izbirni ID imena PostScript in eno koordinato na os:
var
Pdf: THotPDF;
Axes: THPDFVariableFontAxisArray;
Instances: THPDFVariableFontNamedInstanceArray;
I: Integer;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.InspectVariableFont('C:\Fonts\Inter.ttf', Axes, Instances) then
begin
for I := 0 to High(Axes) do
Writeln(Format('%s min=%.1f default=%.1f max=%.1f',
[string(Axes[I].Tag), Axes[I].MinimumValue,
Axes[I].DefaultValue, Axes[I].MaximumValue]));
Writeln(Format('%d named instance(s) defined', [Length(Instances)]));
end
else
Writeln('not a variable font - embed it as an ordinary TrueType face');
finally
Pdf.Free;
end;
end;
Poročanje o razponu osi je pomembno, ker so vrednosti osi omejene na razpon, ki ga deklarira pisava, ne na razpon, ki ga ponuja vaš uporabniški vmesnik. Drsnik, ki uporabniku dovoli zahtevati debelino 1000 pri pisavi, katere os wght se konča pri 900, je treba popraviti v vmesniku, ne tiho na ravni pisave, sicer se bo natisnjen izhod razlikoval od predogleda
Izbira koordinat in izpis dokumenta
Izbira osi je stanjska in velja za pisave, registrirane pozneje. SetVariableFontAxis sprejme štiribajtno tiskljivo oznako ASCII in končno vrednost, vse drugo pa zavrne z izjemo, namesto da bi to tiho prezrl. ClearVariableFontAxes ponastavi izbiro, GetVariableFontAxisSelections pa poroča, kaj je trenutno v čakanju, kar je vredno beležiti v mehanizmih za generiranje poročil, kjer se je več poti kode morda dotaknilo istega objekta dokumenta. Sama družina je izbrana po imenu prek SetFont, povsem tako, kot bi bila izbrana katera koli druga vdelana pisava TrueType:
begin
Pdf := THotPDF.Create(nil);
try
Pdf.BeginDoc;
Pdf.SetVariableFontAxis('wght', 620); // polkrepko, ni poimenovana instanca
Pdf.SetVariableFontAxis('wdth', 87.5); // rahlo zoženo
Pdf.CurrentPage.SetFont('Inter', [], 11);
Pdf.CurrentPage.TextOut(72, 720, 0, 'Quarterly results');
Pdf.ClearVariableFontAxes; // nazaj na privzeto instanco
Pdf.CurrentPage.SetFont('Inter', [], 10);
Pdf.CurrentPage.TextOut(72, 700, 0, 'Prepared by the finance team');
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Dogodek OnVariableFontInstance se sproži ob nastanku vsake instance in poroča o uporabljenih vrednostih osi, kar je najcenejši način, da v dnevniku dokažete, kaj določen PDF dejansko vsebuje. Ker vsak različen nabor koordinat da drugačen program pisave, obravnavajte izbire osi kot del ključa predpomnilnika pisav; mehanika predpomnjenja je opisana v trajnem predpomnilniku podnaborov pisav
Kako je instanciranje povezano s podnaborom in oblikovanjem znakov
Instanciranje se izvede pred izdelavo podnabora, in ta vrstni red je pravilen. Instancirana pisava je navadna statična pisava TrueType, zato jo navaden ustvarjalec podnaborov obravnava kot vsako drugo: izračuna zaprtje znakov, obdrži znake, ki jih dokument dejansko uporablja, in zavrže preostale. Povezavo, ki se je treba zavedati, je, da sta dve različni izbiri osi iste družine dva različna programa pisave, zato dokument, ki meša debelino 400 in debelino 620, vdela dva podnabora, ne pa ene skupne pisave z dvema instancama
Oblikovanje znakov na to načeloma ni prizadeto, v praksi pa je vredno preveriti. Postavitvene funkcije živijo v GSUB in GPOS, ki ju instanciranje ohrani, zato ligature in slogovne alternative še naprej delujejo, kot je opisano v slogovnih alternativah OpenType GSUB. Spremeni se postavljanje: zožena instanca ima ožje pomike kot privzeta, zato je vsaka postavitev, ki je besedilo izmerila pred instanciranjem, izmerila napačne širine. Merite z isto izbiro osi, s katero boste upodabljali, in neskladje izgine
Še ena zadnja obrambna opomba iz implementacije, koristna za vsakogar, ki to pot razširja. Pisave brez navpičnih metrik na mestu klica v Delphiju vseeno ovrednotijo argumente dinamičnih polj, zato so polja ob razčlenjevanju vedno dodeljena, namesto da bi se zanašali na to, da preverjanje HasVerticalMetrics prekine izvajanje mimo praznega indeksa. Gre za vrsto podrobnosti na ravni jezika, ki na videz zavarovano vejo spremeni v kršitev dostopa točno pri tistih pisavah, s katerimi niste testirali
Podpora spremenljivim pisavam se umešča v isti cevovod za pisave kot vdelava, izdelava podnabora in zaprtje znakov, kar je podrobneje opisano v zaprtju podnabora pisav in oblikovanih znakih. Celoten nabor tipografskih funkcij za Delphi in C++Builder je naveden na strani komponente HotPDF PDF za Delphi