Ketika PDF tampak berbeda di mesin yang berbeda, penyebab paling umum adalah font tidak disematkan. Setiap glif dalam PDF membawa properti font yang dapat Anda baca dari Delphi dengan PDFium Component: nama keluarga, nama dasar, ketebalan, sudut miring, dan apakah data glif aktual benar-benar tersimpan dalam file. Setelah Anda dapat memeriksa properti tersebut secara terprogram, diagnosis masalah rendering tipografi menjadi lebih mudah secara signifikan
Properti font dibaca per glif, bukan per halaman
API PDFium Component mengekspos properti font pada level karakter. Setelah membuka dokumen dan mengarahkan ke halaman yang ingin Anda periksa, Anda mengakses properti melalui indeks karakter. Pdf.Character[I] memberikan titik kode Unicode glif di posisi tersebut, dan Pdf.FontFamilyName[I], Pdf.FontBaseName[I], Pdf.FontWeight[I], Pdf.FontItalicAngle[I], serta Pdf.FontEmbedded[I] memberikan metadata font yang sesuai
procedure DescribeFontAt(Pdf: TPdf; CharIndex: Integer);
var
Report: TStringList;
PtSize: Single;
begin
Report := TStringList.Create;
try
PtSize := Pdf.FontSize[CharIndex];
Report.Add('Character : ' + Pdf.Character[CharIndex]);
Report.Add('Family : ' + Pdf.FontFamilyName[CharIndex]);
Report.Add('Base name : ' + Pdf.FontBaseName[CharIndex]);
Report.Add('Weight : ' + IntToStr(Pdf.FontWeight[CharIndex]));
Report.Add('Italic : ' + FloatToStr(Pdf.FontItalicAngle[CharIndex]));
Report.Add('Size (pt) : ' + FloatToStr(PtSize));
Report.Add('Embedded : ' + BoolToStr(Pdf.FontEmbedded[CharIndex], True));
ShowMessage(Report.Text);
finally
Report.Free;
end;
end;
Pola yang sama bekerja di dalam loop untuk setiap karakter pada halaman. Namun, biasanya lebih efisien untuk mengumpulkan nama font unik alih-alih membuat laporan untuk setiap karakter individual
Mendeteksi font yang tidak disematkan saat klik mouse
Cara cepat untuk menghubungkan inspeksi font ke UI adalah merespons klik mouse pada TPdfView dan membaca properti di posisi yang diklik. PdfView.CharIndexAt mengonversi koordinat layar ke indeks karakter, yang kemudian dapat Anda masukkan ke dalam properti per-karakter yang disebutkan di atas
procedure TfrmMain.PdfViewMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
CharIdx: Integer;
begin
if Button <> mbLeft then Exit;
CharIdx := PdfView.CharIndexAt(X, Y);
if CharIdx < 0 then Exit; // clicked empty space
if not Pdf.FontEmbedded[CharIdx] then
ShowMessage('Font "' + Pdf.FontBaseName[CharIdx] + '" is NOT embedded')
else
ShowMessage('Font "' + Pdf.FontBaseName[CharIdx] + '" is embedded');
end;
Melaporkan semua font yang tidak disematkan dalam dokumen
Untuk audit seluruh dokumen, Anda perlu mengiterasi semua halaman dan semua karakter, mengumpulkan nama font yang tidak disematkan. Menggunakan set atau TDictionary menghindari duplikasi:
procedure ReportNonEmbeddedFonts(Pdf: TPdf; Report: TStrings);
var
Page, CharIdx: Integer;
FontName: string;
Seen: TDictionary<string, Boolean>;
begin
Seen := TDictionary<string, Boolean>.Create;
try
for Page := 1 to Pdf.PageCount do
begin
Pdf.PageNumber := Page;
for CharIdx := 0 to Pdf.CharCount - 1 do
begin
if not Pdf.FontEmbedded[CharIdx] then
begin
FontName := Pdf.FontBaseName[CharIdx];
if not Seen.ContainsKey(FontName) then
begin
Seen.Add(FontName, True);
Report.Add('Page ' + IntToStr(Page) + ': ' + FontName);
end;
end;
end;
end;
finally
Seen.Free;
end;
end;
Menyimpan data font yang disematkan ke disk
PDFium Component juga memungkinkan Anda mengekstrak byte font yang disematkan ke dalam stream. Ini berguna ketika Anda perlu mengaudit apakah font yang disematkan dalam PDF adalah versi yang sama dengan yang ada di sistem Anda, atau ketika Anda ingin mengekstrak font untuk keperluan analisis:
procedure SaveEmbeddedFont(Pdf: TPdf; CharIndex: Integer;
const OutputPath: string);
var
Stream: TMemoryStream;
begin
Stream := TMemoryStream.Create;
try
Pdf.GetEmbeddedFont(CharIndex, Stream);
if Stream.Size > 0 then
Stream.SaveToFile(OutputPath)
else
ShowMessage('No embedded font data at character ' + IntToStr(CharIndex));
finally
Stream.Free;
end;
end;
Selalu periksa Pdf.FontEmbedded[CharIndex] sebelum memanggil GetEmbeddedFont. Ketika font tidak disematkan, stream yang dikembalikan akan kosong, sehingga pemeriksaan tersebut juga menghindari penulisan file output kosong
Untuk mempelajari lebih lanjut tentang rendering dokumen, muat dan tampilkan PDF, lihat PDFium Delphi VCL Component