Jawaban singkat untuk tiket dukungan itu adalah ya, dengan batasan. HotPDF 2.730.0 terbangun di Free Pascal 3.2.2 dan Lazarus 4.6 untuk Win64, dan jalur inti create, load, serta save bekerja. Yang tidak mengikuti adalah apa pun yang bertumpu pada objek codec native yang statis terlink atau pada anonymous method Delphi
Pertanyaannya biasanya datang dengan cara yang sama: sebuah tim menstandarkan diri pada Lazarus untuk alat lintas platform, atau mewarisi kode basis Free Pascal, lalu menginginkan komponen PDF yang sama yang sudah mereka lisensikan untuk Delphi. Mem-port pustaka Delphi yang matang jarang sekadar soal sintaks. Bagian menariknya adalah apa yang dibongkar oleh port tentang di mana pustaka itu diam-diam terikat pada satu toolchain, dan dalam kasus ini ikatannya duduk di dua tempat yang sangat spesifik: ABI berkas objek dari codec yang dibundel, dan fitur kompiler yang bersembunyi di balik sebuah simbol versi
Apa yang dibutuhkan Free Pascal 3.2.2 sebelum HPDFDoc terkompilasi
HotPDF terkompilasi di Free Pascal hanya dalam mode Delphi, dan hanya saat direktori unit LCL Lazarus berada di jalur pencarian. Keduanya tidak bisa ditawar. HotPDF.inc mengalihkan kompiler dengan {$MODE DELPHI} dan {$H+} di dalam blok {$IFDEF FPC} serta menolak apa pun yang lebih tua dengan {$FATAL} saat FPC_FULLVERSION di bawah 30202, jadi instalasi 3.0.x gagal dengan nyaring alih-alih menghasilkan unit rusak. Paket runtime Lazarus HotPDFLaz.lpk mengodekan sisanya: LCL sebagai paket wajib dan -Mdelphi sebagai opsi kustom
Persyaratan LCL mengejutkan orang yang hanya ingin output konsol, tetapi ia struktural. HPDFFPCCompat menyediakan tipe VCL Delphi yang tak punya padanan di Free Pascal, memetakan TMetafile dan TMetafileCanvas ke kelas bitmap dan canvas LCL serta meng-alias TRichEdit ke TMemo, sementara HPDFDoc meng-alias TPNGObject ke Graphics.TPortableNetworkGraphic. Perlakukan itu sebagai shim waktu-kompilasi, bukan paritas fitur: kelas metafile yang ditopang bitmap menjaga unit tetap terkompilasi, ia tidak membuat jalur metafile berperilaku seperti di Delphi. Bahkan smoke test non-GUI pun menarik Interfaces, dan skrip build meneruskan -Fu untuk lcl\units\x86_64-win64 serta direktori output lazutils
Mengapa D2009+ tidak bisa menjadi gerbang versi
Menggoda untuk memperlakukan build Free Pascal sebagai kompiler modern dan sekadar mendefinisikan simbol fitur Delphi terbaru. HotPDF tidak, dan alasannya layak dinyatakan terus terang: D2009+ tidak berarti string Unicode saja, ia juga menggerbangi unit yang API publiknya diekspresikan dengan anonymous method. Free Pascal 3.2.2 tidak mendukung anonymous method Delphi maupun API-API itu, jadi meminjam simbol tersebut akan menyeret kode yang tidak mungkin terkompilasi. Klausa uses HPDFDoc karena itu membawa dua ekor kondisional terpisah, dan tumpang tindih di antara keduanya disengaja, bukan kebetulan
uses
// ...
HPDFJavaScript,
HPDFFormCalcGraph
{$IFDEF FPC}
, HPDFFPCCodecStubs,
HPDFCMS,
HPDFWinCertSigner
{$ENDIF}
{$IFDEF D2009+}
, HPDFXFARuntime,
HPDFCMS,
HPDFWinCertSigner,
HPDFSignVerify,
HPDFSignatureBatch
{$ENDIF};
Mengapa codec native berhenti di linker?
Karena mereka objek Win64 COFF yang dihasilkan oleh satu toolchain tertentu, dan tak ada linker Free Pascal di Win64 yang mau mengonsumsinya: bukan linker internal, bukan jalur GNU ld eksternal. Ini masalah ABI berkas objek, bukan masalah Pascal, dan seberapapun banyak sumber kondisional tak akan memperbaikinya. Pustaka mengambil satu-satunya jalan jujur yang tersedia. Setiap direktif {$L} yang menarik objek codec statis dibungkus {$IFNDEF FPC}, sehingga build Free Pascal sekadar melewatinya, dan HPDFFPCCodecStubs kemudian menyuplai setiap simbol eksternal yang hilang sebagai stub yang melempar alih-alih mengembalikan
// 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;
Tabel stub itu panjang, dan membacanya memberi tahu Anda persis kemampuan mana yang hari ini hanya milik Delphi: titik masuk deflate zlib-ng dan zopfli, kompresi dan dekompresi libjpeg, codec OpenJPEG JPEG 2000, libtiff beserta inisialisasi per-kompresinya, encode dan decode JBIG2, titik masuk transformasi warna Little-CMS, serta primitif AES. Pilihan desain di balik stub lebih penting daripada daftarnya. Simbol yang hilang saat link memberi Anda tembok undefined references dari unit yang belum pernah Anda sentuh; stub yang melempar ENotSupportedException memberi Anda build yang jalan, pesan yang menyebut alasannya, dan stack trace yang menunjuk lokasi pemanggilan. Itu juga berarti build Free Pascal tak pernah diam-diam menghasilkan byte salah di tempat build Delphi menghasilkan byte benar. Perhatikan efek orde keduanya juga: menjalankan codec gambar tak terpercaya di proses terisolasi adalah keputusan yang hanya muncul di build Delphi, karena build Free Pascal tak punya dekoder native in-process untuk di-sandbox sejak awal
Kompresi: baris pertama yang diubah adalah cmNone
Sebelum mem-port apa pun lainnya, atur Compression ke cmNone. THPDFCompressionMethod menawarkan tepat dua nilai, cmNone dan cmFlateDecode, dan yang kedua bermuara langsung ke titik masuk deflate yang berupa stub di build Free Pascal. Verifikasi dulu model objek inti dengan kompresi mati, lalu putuskan apa lagi yang Anda butuhkan. Itulah urutan yang dipakai smoke test yang dikirim: buat dokumen satu halaman tanpa kompresi, muat ulang, dan asersi jumlah halaman kembali satu. Output tanpa kompresi lebih besar, dan tetap PDF yang sah sepenuhnya
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 reaches a stubbed 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.
Apa yang terjadi pada rendering halaman paralel?
Ia tetap terkompilasi, tetap mengembalikan bitmap yang benar, dan berhenti menjadi paralel. THotPDF.RenderLoadedPagesParallel dan THotPDF.RenderLoadedPagesParallelOrdered dibangun di atas TThread.CreateAnonymousThread dengan closure procedure inline, yang tak bisa diekspresikan Free Pascal 3.2.2, sehingga cabang Free Pascal menjalankan fallback serial yang deterministik: ia menyusuri indeks halaman secara berurutan, memanggil RenderLoadedPageToBitmap untuk masing-masing, dan menghitung keberhasilannya. Bentuk API, nilai kembali, dan array output tak berubah, dan itulah yang memungkinkan satu basis kode terbangun dua arah
var
Bitmaps: THPDFBitmapArray;
Info: THPDFParallelRenderPipelineInfo;
Rendered: Integer;
begin
Rendered := Pdf.RenderLoadedPagesParallel([0, 1, 2, 3], 150, 4,
Bitmaps, Info);
// Delphi: Info.WorkerCount is whatever the memory budget allowed
// Free Pascal: Info.WorkerCount is always 1, pages in index order
if Info.WorkerCount = 1 then
LogSerialFallback(Rendered, Info.RequestedWorkerCount);
Fallback itu tidak diam, dan itulah bagian yang layak dirancang di sekelilingnya. Ia mengisi THPDFParallelRenderPipelineInfo dengan jujur: PageCount dari permintaan, RequestedWorkerCount yang menggemakan permintaan Anda, WorkerCount diatur 1, serta hitungan selesai dan tersampaikan yang cocok dengan yang benar-benar kembali. Kode yang sudah menginspeksi Info untuk mengukur progress bar atau anggaran memori tetap bekerja dan membaca kebenaran, bukan asumsi. Jika rencana throughput Anda bergantung pada pipeline render paralel dan model backpressure-nya, rencana itu adalah rencana Delphi; di Free Pascal, anggarkan biaya satu-thread merender halaman ke bitmap dikalikan jumlah halaman
Build mana yang benar-benar Anda kirim?
Pilih berdasarkan kemampuan, bukan preferensi. Jika alur kerja Anda adalah perakitan dokumen, teks dan gambar vektor, pengisian form, loading dan saving, build Free Pascal di Win64 menutupnya, dan Anda sebaiknya memvalidasi dengan kompresi mati sebelum menyalakan apa pun. Jika melibatkan gambar JPEG atau JPEG 2000 atau TIFF atau JBIG2, transformasi warna ICC, output terkompresi, atau throughput yang bergantung pada banyak core, tetaplah di Delphi atau C++Builder untuk sekarang. Batasnya digambar oleh ABI berkas objek dan satu fitur bahasa yang hilang, keduanya terlihat di sumber alih-alih terkubur di matriks dukungan, dan keduanya gagal dengan error bernama alih-alih hasil yang salah
Paket Free Pascal dan Lazarus dikirim dalam distribusi yang sama dengan unit Delphi dan C++Builder, jadi satu lisensi mencakup keduanya dan Anda bisa menguji jalur Lazarus terhadap dokumen Anda sendiri sebelum berkomitmen; halaman produk HotPDF Delphi PDF Component membawa matriks dukungan kompiler terkini dan referensi API lengkap