Trumpas atsakymas į tą palaikymo bilietą — taip, bet su ribojimais. HotPDF 2.730.0 konstruojamas su Free Pascal 3.2.2 ir Lazarus 4.6 Win64 aplinkoje, ir pagrindiniai kūrimo, įkėlimo bei išsaugojimo keliai veikia. Ko neseka — viskas, kas remiasi statiškai susietu natyviu kodeko objektu arba Delphi anonominiais metodais
Klausimas paprastai atkeliauja taip pat: komanda pereina prie Lazarus kelių platformų įrankiui arba paveldi Free Pascal kodą ir nori to paties PDF komponento, kurį jau licenzijuoja Delphi. Brandaus Delphi bibliotekos perkėlimas retai kada yra sintaksės klausimas. Įdomiausia dalis — ką tas perkėlimas atskleidžia apie vietas, kur biblioteka tyliai buvo susieta su viena įrankių grandine, o čia susietumas sėdi dviejose labai konkrečiose vietose: pridėtų kodekų objektinio failo ABI ir kompiliatoriaus galimybių, slepiančiose už versijos simbolio
Ko Free Pascal 3.2.2 reikia, kol HPDFDoc sukompiliuojamas
HotPDF Free Pascal aplinkoje kompiliuojasi tik Delphi režimu ir tik tada, kai Lazarus LCL modulių katalogai yra paieškos kelyje. Abi sąlygos nesiderėja. HotPDF.inc perjungia kompiliatorių savo {$IFDEF FPC} bloke su {$MODE DELPHI} ir {$H+}, o senesnes versijas atmeta {$FATAL}, kai FPC_FULLVERSION žemiau 30202, tad 3.0.x instaliacija žlunga garsiai, užuot pagaminusi sugadintą modulį. Lazarus vykdymo paketas HotPDFLaz.lpk užkoduoja likusį: LCL kaip privalomą paketą ir -Mdelphi kaip pasirinktinę parinktį
LCL reikalavimas nustebina tuos, kurie nori tik konsolės išvesties, bet jis struktūrinis. HPDFFPCCompat tiekia Delphi VCL tipus, kuriems Free Pascal neturi atitikmenų: TMetafile ir TMetafileCanvas sudeda ant LCL taškinių piešinių ir drobių klasių, TRichEdit pravardžiuoja kaip TMemo, o HPDFDoc TPNGObject pravardžiuoja kaip Graphics.TPortableNetworkGraphic. Laikykite tai kompiliavimo laiko tarpinėmis, o ne galimybių lygybe: metafailo klasė, paremta taškiniu piešiniu, palieka modulį kompiliuojamą, bet nedaro to, kad metafailo keliai elgtųsi kaip Delphi. Net ne GUI dūmų testas traukia Interfaces, o kūrimo scenarijus perduoda -Fu su lcl\units\x86_64-win64 ir lazutils išvesties katalogu
Kodėl D2009+ negali sutapti su versijos vartais
Vilioja Free Pascal variantą laikyti moderniu kompiliatoriumi ir tiesiog apibrėžti naujausią Delphi galimybių simbolį. HotPDF to nedaro, ir priežastį verta pasakyti tiesiai: D2009+ nereiškia vien Unicode eilučių — jis taip pat uždaro vartus moduliams, kurių viešąją API išreiškia anoniminiai metodai. Free Pascal 3.2.2 nepalaiko nei Delphi anonominių metodų, nei tų API, tad simbolio pasiskolinimas įtrauktų kodą, kuris nesikompiliuoja. Todėl HPDFDoc uses sekcija neša dvi atskiras sąlygines uodegas, ir jų persidengimas sąmoningas, o ne atsitiktinis
uses
// ...
HPDFJavaScript,
HPDFFormCalcGraph
{$IFDEF FPC}
, HPDFFPCCodecStubs,
HPDFCMS,
HPDFWinCertSigner
{$ENDIF}
{$IFDEF D2009+}
, HPDFXFARuntime,
HPDFCMS,
HPDFWinCertSigner,
HPDFSignVerify,
HPDFSignatureBatch
{$ENDIF};
Kodėl natyvūs kodekai sustoja prie susiejiklio?
Nes tai vienos konkrečios įrankių grandinės išduoti Win64 COFF objektai, kurių Win64 nė vienas Free Pascal susiejiklis neprasiurbia: nei vidinis susiejiklis, nei išorinis GNU ld kelias. Tai objektinio failo ABI problema, o ne Pascal problema, ir jokios sąlyginės kodo dozės jos nesutvarkys. Biblioteka ima vienintelį sąžiningą kelią. Kiekviena {$L} direktyva, traukianti statinį kodeko objektą, apvyniota {$IFNDEF FPC}, tad Free Pascal variantas jos tiesiog praleidžia, o HPDFFPCCodecStubs paskui kiekvieną trūkstamą išorinį simbolį paduoda kaip pakaitalą, kuris vietoj grąžinimo pakelia išimtį
// HPDFFPCCodecStubs.pas
function HPDFFPCNativeCodecUnavailable: PtrUInt;
begin
raise ENotSupportedException.Create(
'This native codec is not available in the Free Pascal build');
end;
function HPDFFPCStub_deflate: PtrUInt; cdecl;
public name 'deflate';
begin
Result := HPDFFPCNativeCodecUnavailable;
end;
Tas pakaitalų sąrašas ilgas, ir jį paskaitęs tiksliai sužinosite, kurios galimybės šiandien yra tik Delphi: zlib-ng ir zopfli deflate įėjimo taškai, libjpeg glaudinimas ir išglaudinimas, OpenJPEG JPEG 2000 kodekas, libtiff su jo glaudinimo inicijatoriais, JBIG2 kodavimas ir dekodavimas, Little-CMS spalvų transformacijos įėjimo taškai ir AES primitivai. Už pakaitalų slypinti projektavimo sprendimas svarbesnis už patį sąrašą. Trūkstamas simbolis susiejimo metu duoda sieną neapibrėžtų nuorodų iš modulio, kurio niekada nelietėte; pakaitalas, keliantis ENotSupportedException, duoda variantą, kuris veikia, pranešimą su priežastimi ir dėklo pėdsaką, rodantį į iškvietimo vietą. Tai taip pat reiškia, kad Free Pascal variantas niekada nepastebimai negamins neteisingų baitų ten, kur Delphi variantas pagamintų teisingus. Pastebėkite ir antro lygio pasekmę: nepatikimų vaizdų kodekų paleidimas izoliuotame procese yra sprendimas, kuris kyla tik Delphi variante, nes Free Pascal variante iš viso nėra proceso vidinio natyvaus dekoderio, kurį būtų galima izoliuoti
Glaudinimas: pirmoji keičiama eilutė yra cmNone
Prieš perkeliant ką kita, nustatykite Compression į cmNone. THPDFCompressionMethod teikia tik dvi reikšmes, cmNone ir cmFlateDecode, o antroji veda tiesiai į deflate įėjimo taškus, kurie Free Pascal variante yra pakaitalai. Iš pradžių patikrinkite pagrindinį objektų modelį su išjungtu glaudinimu, paskui spręskite, ko dar reikia. Tokia tvarka, kuria eina pristatomas dūmų testas: sukuriamas vienpusis neglaudintas dokumentas, jis persikeliamas ir tikrinama, ar puslapių skaičius grįžo lygus vienam. Neglaudinta išvestis didesnė, ir tai vis tiek visiškai teisingas PDF
program HotPDFLazarusSmoke;
{$mode delphi}
{$H+}
uses
Interfaces, SysUtils, HPDFDoc;
var
Pdf, Reloaded: THotPDF;
OutputFile: string;
PageCount: Integer;
begin
OutputFile := IncludeTrailingPathDelimiter(GetTempDir) +
'HotPDF-FPC-Smoke.pdf';
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := OutputFile;
Pdf.Compression := cmNone; // cmFlateDecode pasiekia pakaitalu pakeistą simbolį
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 12);
Pdf.CurrentPage.TextOut(72, 72, 0, 'HotPDF Free Pascal smoke test');
Pdf.EndDoc;
finally
Pdf.Free;
end;
Reloaded := THotPDF.Create(nil);
try
PageCount := Reloaded.LoadFromFile(OutputFile);
if PageCount <> 1 then
raise Exception.CreateFmt('Expected one page, got %d', [PageCount]);
finally
Reloaded.Free;
end;
end.
Kas nutinka lygiagretaus puslapių atvaizdavimo?
Jis vis tiek sukompiliuojasi, vis tiek grąžina teisingus taškinius piešinius ir nustoja būti lygiagretus. THotPDF.RenderLoadedPagesParallel ir THotPDF.RenderLoadedPagesParallelOrdered pastatyti ant TThread.CreateAnonymousThread su inline procedure uždaru, kurio Free Pascal 3.2.2 neišreiškia, tad Free Pascal šaka vykdo deterministinę nuoseklią atsarginę eigą: eina per puslapių indeksus tvarka, kiekvienam iškviečia RenderLoadedPageToBitmap ir skaičiuoja sėkmes. API forma, grąžinama reikšmė ir išvesties masyvas nepakitę — būtent todėl viena kodų bazė konstruojama abiejais būdais
var
Bitmaps: THPDFBitmapArray;
Info: THPDFParallelRenderPipelineInfo;
Rendered: Integer;
begin
Rendered := Pdf.RenderLoadedPagesParallel([0, 1, 2, 3], 150, 4,
Bitmaps, Info);
// Delphi: Info.WorkerCount — kiek leido atminties biudžetas
// Free Pascal: Info.WorkerCount visada 1, puslapiai indeksų tvarka
if Info.WorkerCount = 1 then
LogSerialFallback(Rendered, Info.RequestedWorkerCount);
Atsarginė eiga ne tyla — būtent tai verta įvertinti projektuojant. Ji sąžiningai užpildo THPDFParallelRenderPipelineInfo: PageCount iš užklausos, RequestedWorkerCount, atkartojantis tai, ko prašėte, WorkerCount nustatytas į 1, o užbaigtų ir pristatytų skaičiai sutampa su tuo, kas tikrai grįžo. Kodas, jau žiūrintis į Info, kad suskaičiuotų pažangos juostą ar atminties biudžetą, toliau veikia ir skaito tiesą, o ne prielaidą. Jei jūsų pralaidumo planas remiasi lygiagretaus atvaizdavimo konvejeriu ir jo atgalinio spaudimo modeliu, tas planas yra Delphi planas; Free Pascal aplinkoje planuokite puslapio atvaizdavimo į taškinį piešinį viengijos kainą, padaugintą iš puslapių skaičiaus
Kurį variantą iš tikrųjų tiekti?
Rinkitės pagal galimybes, o ne pagal simpatijas. Jei jūsų procesas yra dokumentų surinkimas, tekstas ir vektorinis braižymas, formų užpildymas, įkėlimas ir išsaugojimas, Free Pascal variantas Win64 tai dengia, ir verta patikrinti su išjungtu glaudinimu, prieš įjungiant ką nors kitą. Jei procesas liečia JPEG ar JPEG 2000 ar TIFF ar JBIG2 vaizdus, ICC spalvų transformacijas, glaustą išvestį ar pralaidumą, priklausantį nuo daug branduolių, kol kas likite prie Delphi ar C++Builder. Ribą nubrėžia objektinio failo ABI ir trūkstama kalbos galimybė — abi matomos šaltinyje, o ne palaidotos palaikymo matricoje, ir abi žlunga su pavadinta klaida, o ne su neteisingu rezultatu
Free Pascal ir Lazarus paketas tiekiamas tame pačiame platinime kaip Delphi ir C++Builder moduliai, tad viena licenzija dengia abu, ir Lazarus kelią galite išbandyti su savais dokumentais, prieš įsipareigodami; HotPDF Delphi PDF Component produkto puslapyje yra dabartinė kompiliatorių palaikymo matrica ir pilna API dokumentacija