Det korte svaret på den støttesaken er ja, med grenser. HotPDF 2.730.0 bygges på Free Pascal 3.2.2 og Lazarus 4.6 for Win64, og kjernebanene for create, load og save virker. Det ikke følger med, er alt som hviler på et statisk linket innfødt kodek-objekt eller på Delphi-anonyme metoder
Spørsmålet ankommer vanligvis på samme måte: et team standardiserer på Lazarus for et tverrplattformverktøy, eller arver en Free Pascal-kodebase, og vil ha den samme PDF-komponenten de allerede lisensierer for Delphi. Å portere et modent Delphi-bibliotek er sjelden et spørsmål om syntaks. Den interessante delen er hva porten avslører om hvor biblioteket stille var koblet til én verktøykjede, og i dette tilfellet sitter koblingen på to helt konkrete steder: objektfil-ABI-en til de medfølgende kodekene, og kompilatorfunksjonene som gjemmer seg bak et versjonssymbol
Hva Free Pascal 3.2.2 trenger før HPDFDoc kompilerer
HotPDF kompilerer under Free Pascal bare i Delphi-modus, og bare når Lazarus LCL-unit-katalogene er på søkestien. Ingen av delene er forhandlingsbar. HotPDF.inc bytter kompilatoren med {$MODE DELPHI} og {$H+} inne i sin {$IFDEF FPC}-blokk og nekter alt eldre med en {$FATAL} når FPC_FULLVERSION er under 30202, så en 3.0.x-installasjon feiler høyt i stedet for å produsere en ødelagt unit. Lazarus kjøretidspakken HotPDFLaz.lpk koder resten: LCL som påkrevd pakke og -Mdelphi som tilpasset alternativ
LCL-kravet overrasker folk som bare vil ha konsollutdata, men det er strukturelt. HPDFFPCCompat leverer Delphi VCL-typene Free Pascal ikke har noen ekvivalent for, ved å avbilde TMetafile og TMetafileCanvas på LCL bitmap- og canvas-klasser og aliasere TRichEdit til TMemo, mens HPDFDoc aliaserer TPNGObject til Graphics.TPortableNetworkGraphic. Behandle dem som kompileringstids-shims, ikke funksjonsparitet: en metafile-klasse støttet av en bitmap holder unit-en kompilerende, den får ikke metafile-banene til å oppføre seg slik de gjør på Delphi. Selv røyktesten uten GUI trekker inn Interfaces, og byggskriptet sender -Fu for lcl\units\x86_64-win64 og lazutils utdatakatalog
Hvorfor D2009+ ikke kan tjene som versjonsport
Det er fristende å behandle Free Pascal-bygget som en moderne kompilator og bare definere det nyeste Delphi-funksjonssymbolet. HotPDF gjør ikke det, og grunnen er verdt å si rett ut: D2009+ betyr ikke bare Unicode-strenger, den porter også unit-er hvis offentlige API uttrykkes med anonyme metoder. Free Pascal 3.2.2 støtter verken Delphi-anonyme metoder eller de API-ene, så å låne symbolet ville dra inn kode som ikke kan kompilere. Uses-klausulen i HPDFDoc bærer derfor to separate betingede haler, og overlappen mellom dem er villet snarere enn tilfeldig
uses
// ...
HPDFJavaScript,
HPDFFormCalcGraph
{$IFDEF FPC}
, HPDFFPCCodecStubs,
HPDFCMS,
HPDFWinCertSigner
{$ENDIF}
{$IFDEF D2009+}
, HPDFXFARuntime,
HPDFCMS,
HPDFWinCertSigner,
HPDFSignVerify,
HPDFSignatureBatch
{$ENDIF};
Hvorfor stopper de innfødte kodekene ved linkeren?
Fordi de er Win64 COFF-objekter avgitt av én bestemt verktøykjede, og ingen av Free Pascal-linkerne på Win64 vil konsumere dem: verken den interne linkeren eller den eksterne GNU ld-banen. Dette er et objektfil-ABI-problem, ikke et Pascal-problem, og ingen mengde betinget kilde fikser det. Biblioteket tar den eneste ærlige ruten tilgjengelig. Hvert {$L}-direktiv som trekker inn et statisk kodek-objekt er pakket inn i {$IFNDEF FPC}, så Free Pascal-bygget utelater dem rett og slett, og HPDFFPCCodecStubs leverer deretter hvert manglende eksterne symbol som en stub som utløser unntak i stedet for å returnere
// 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;
Den stub-tabellen er lang, og å lese den forteller deg nøyaktig hvilke kapabiliteter som er Delphi-alene i dag: zlib-ng- og zopfli-deflate-inngangspunktene, libjpeg-komprimering og dekomprimering, OpenJPEG JPEG 2000-kodeken, libtiff og dets per-komprimering-initialiserere, JBIG2-koding og -dekoding, Little-CMS fargetransform-inngangspunktene, og AES-primitivene. Designvalget bak stubbene betyr mer enn listen. Et manglende symbol ved link-tid gir deg en vegg av udefinerte referanser fra en unit du aldri rørte; en stub som utløser ENotSupportedException gir deg et bygg som kjører, en melding som navngir grunnen, og et stacktrace som peker på kallstedet. Det betyr også at et Free Pascal-bygg aldri stille produserer feil byte der et Delphi-bygg ville produsert korrekte. Merk også andreordseffekten: kjøring av utruelige bildekodeker i en isolert prosess er et valg som bare oppstår på Delphi-bygget, for et Free Pascal-bygg har ingen innprosess innfødt dekoder å sandkasse i det hele tatt
Komprimering: den første linjen å endre er cmNone
Før du porterer noe annet, sett Compression til cmNone. THPDFCompressionMethod tilbyr nøyaktig to verdier, cmNone og cmFlateDecode, og den andre ruter rett inn i deflate-inngangspunktene som er stubber i et Free Pascal-bygg. Verifiser kjernens objektmodell først med komprimering av, og avgjør så hva du ellers trenger. Det er rekkefølgen den medfølgende røyktesten bruker: opprett et ensides ukomprimert dokument, last det inn på nytt, og påstå at sideantallet kom tilbake som én. Ukomprimert utdata er større, og den er fremdeles en helt gyldig 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 når et stubbet symbol
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.
Hva skjer med parallell sidengjengivelse?
Den kompilerer fortsatt, returnerer fortsatt korrekte bitmapser, og slutter å være parallell. THotPDF.RenderLoadedPagesParallel og THotPDF.RenderLoadedPagesParallelOrdered er bygget på TThread.CreateAnonymousThread med en inline procedure-lukking, som Free Pascal 3.2.2 ikke kan uttrykke, så Free Pascal-grenen kjører en deterministisk seriell reserve: den går sideindeksene i rekkefølge, kaller RenderLoadedPageToBitmap for hver, og teller suksessene. API-formen, returverdien og utdatamatrisen er uendret, noe som er det som lar én kodebase bygges begge veier
var
Bitmaps: THPDFBitmapArray;
Info: THPDFParallelRenderPipelineInfo;
Rendered: Integer;
begin
Rendered := Pdf.RenderLoadedPagesParallel([0, 1, 2, 3], 150, 4,
Bitmaps, Info);
// Delphi: Info.WorkerCount er hva minnebudsjettet tillot
// Free Pascal: Info.WorkerCount er alltid 1, sider i indeksrekkefølge
if Info.WorkerCount = 1 then
LogSerialFallback(Rendered, Info.RequestedWorkerCount);
Reserven er ikke stille, noe som er delen verdt å designe rundt. Den fyller THPDFParallelRenderPipelineInfo ærlig: PageCount fra forespørselen, RequestedWorkerCount som gjentar hva du ba om, WorkerCount satt til 1, og de fullførte og leverte tellerne som stemmer med det som faktisk kom tilbake. Kode som allerede inspekterer Info for å dimensjonere en fremdriftslinje eller et minnebudsjett fortsetter å virke og leser sannheten snarere enn en antagelse. Hvis gjennomstrømningsplanen din avhenger av den parallelle gjengivelsespipelinen og dens mottrykksmodell, er den planen en Delphi-plan; på Free Pascal, budsjetter for den entrådede kostnaden av å gjengi en side til en bitmap ganget med sideantallet
Hvilket bygg bør du faktisk levere?
Velg etter kapabilitet, ikke etter preferanse. Hvis arbeidsflyten din er dokumentsammenstilling, tekst- og vektortegning, skjemautfylling, innlasting og lagring, dekker Free Pascal-bygget på Win64 det, og du bør verifisere med komprimering av før du slår på noe som helst. Hvis den involverer JPEG-, JPEG 2000-, TIFF- eller JBIG2-bilder, ICC-fargetransformasjoner, komprimert utdata, eller gjennomstrømning som avhenger av mange kjerner, bli på Delphi eller C++Builder foreløpig. Grensen tegnes av en objektfil-ABI og en manglende språkfunksjon, som begge er synlige i kilden snarere enn begravd i en støttematrise, og som begge feiler med en navngitt feil snarere enn et feil resultat
Free Pascal- og Lazarus-pakken leveres i samme distribusjon som Delphi- og C++Builder-unit-ene, så en lisens dekker begge, og du kan teste Lazarus-banen mot dine egne dokumenter før du forplikter deg til den; HotPDF Delphi PDF Component-produktsiden fører den gjeldende kompilatorstøttematrisen og den fullstendige API-referansen