HotPDF, bir sayfanın içerik akışındaki her operatörü dolaşır ve her birini VisitLoadedPageContentOperators aracılığıyla kodunuza teslim eder. Her operatör için bir eylem seçersiniz: koruyun, silin, kendi baytlarınızla değiştirin, dolaşmayı durdurun veya tüm düzenlemeyi reddedin. Her operatör korunduğunda, yeniden yazılan akış özgününle bayt bayt özdeştir; bu da mekanizmayı sizin oluşturmadığınız belgeler üzerinde çalıştırmayı güvenli kılan özelliktir
İçerik akışı düzenleme, PDF araçlarının genellikle yanlış gittiği yerdir. Bir akış, bir belge ağacı değil, bir yığın makinesi üzerindeki bir operatör dizisidir ve kod çözülmüş baytlar üzerinde bir düzenli ifade çalıştırmanın naif yaklaşımı, bir dize sabit değeri bir operatöre benzeyen bir şey içerdiği anda veya satır içi bir görüntü rastgele ikili veri içerdiği anda bozulur. Akışı zaten belirteçlere ayırmış bir ziyaretçinin bu sorunu yoktur
Operatör Düzeyinde Erişimle Gerçekte Ne Yapabilirsiniz?
Üç görev ailesi vardır. Denetleme: bir sayfanın bilinen bir kümenin dışında kaç kez renk ayarladığını saymak veya gömülü olmayan bir yazı tipiyle çizilmiş metni bulmak. Kaldırma: işaretli içerik olarak çizilmiş bir filigranı silmek veya belirli bir görüntü çağrısını ayıklamak. Ve normalleştirme: bir operatör biçimini, sonraki bir tüketicinin daha iyi işlediği eşdeğer bir biçimle değiştirmek
Bunların her biri bir gereksinimi paylaşır: akışın geri kalan yüzde 99'unu dokunulmamış bırakabilmelisiniz. HotPDF'in sözdizimi ağacı, kaynağın bir kopyasını artı kompakt aralıkları saklar ve düzenlemeler sıralanmış, çakışmayan katmanlardır. Sonucu yazmak, dokunulmamış aralıkları doğrudan kopyalar ve yalnızca bir şey değiştirdiğiniz yerlerde değiştirme baytları yayar, bu yüzden hiçbir şey yapmayan bir gidiş-dönüş sapma getiremez
Ziyaretçi Sözleşmesi
Arayüzü uygulayın veya olayı atayın, ardından bir denetim için ApplyChanges'ı false, bir yeniden yazma için true olarak ayarlayarak ziyaret yöntemini çağırın. Olay verisi; aşamayı, operatör adını, işlenen sayısını, bayt aralığını, geçerli iç içe geçme durumunu ve işlenenleri okumak için ödünç alınmış bir görünümü taşır:
uses
HPDFDoc, HPDFContentStream;
procedure TAuditor.HandleOperator(Sender: TObject;
var EventData: THPDFContentOperatorEventData);
var
Bytes: TBytes;
begin
if EventData.Phase <> covpOperator then
Exit;
// İşaretli içerik içinde çizilen metin gösteren operatörleri say
if (EventData.OperatorName = 'Tj') or
(EventData.OperatorName = 'TJ') then
begin
Inc(FTextOperators);
if EventData.State.MarkedContentDepth > 0 then
Inc(FTextInsideMarkedContent);
end;
// Bir işleneni yalnızca ihtiyacınız olduğunda okuyun
if EventData.OperatorName = 'Do' then
if EventData.View.GetOperandBytes(0, Bytes) then
NoteXObjectUse(TEncoding.ANSI.GetString(Bytes));
EventData.Action := coaKeep;
end;
procedure TAuditor.Run(const FileName: string);
var
Pdf: THotPDF;
Stats: THPDFContentOperatorVisitStatistics;
I: Integer;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile(FileName) <= 0 then
Exit;
Pdf.OnContentOperator := HandleOperator;
for I := 0 to Pdf.LoadedPageCount - 1 do
Pdf.VisitLoadedPageContentOperators(I, False, Stats); // yalnızca denetim
Writeln(Format('%d operators visited, max q/Q depth %d',
[Stats.VisitedOperatorCount, Stats.MaximumGraphicsStateDepth]));
finally
Pdf.Free;
end;
end;
Görünüm Neden Değiştirilebilir Değil de Ödünç Alınmıştır?
Geri çağrı hiçbir zaman değiştirilebilir bir sözdizimi ağacı almaz. Talep üzerine geçerli işlemin baytlarını veya belirli bir işleneni getirebilen bir görünüm alır, hepsi bu kadardır. Bunun yerine her değişiklik, eylem ve değiştirme alanlarından geçer
Bu dolaylılık bir formalite değildir. Doğrudan ağaç değişikliği, bir ziyaretçinin değiştirme bütçesini ve çakışan düzenleme kontrolünü atlamasına izin verirdi ve bir bayt aralığı katman modelinde çakışan düzenlemeler, gürültülü şekilde bozuk olmak yerine sessizce yanlış olan bir çıktı üretir. Değişiklikleri eylem alanı üzerinden yönlendirmek, ziyaretçinin ne amaçladığından bağımsız olarak her düzenlemenin aynı şekilde doğrulandığı anlamına gelir
Talep üzerine okuma, yaygın durumu da ucuz tutar. Yalnızca operatör adlarını sayan bir denetim, işlenen baytlarını hiçbir zaman somutlaştırmaz; bu, yüz binlerce işlem içeren bir içerik akışında önemlidir
Durum Alanı Her Zaman Girişi Tanımlar
Her olay; grafik durumu derinliğini, metin nesnesi derinliğini, işaretli içerik derinliğini ve uyumluluk bölümü derinliğini, o operatör çalıştırılmadan hemen önce özgün girişte oldukları haliyle taşır. Ziyaretçiniz önceki operatörleri silmiş veya değiştirmiş olsa bile bu geçerlidir
Durumu düzenlenmiş çıktı yerine özgün girişe bağlamak, pratik bir getirisi olan kasıtlı bir seçimdir: aynı denetimin aynı belge üzerinde iki kez çalıştırılması özdeş sonuçlar üretir ve düzenlemelerle birlikte çalışan bir denetim kendi referans çerçevesini kaydırmaz. Çıktıdaki derinliği bilmeniz gerekiyorsa neyi sildiğinizi bilirsiniz, bu yüzden onu hesaplayabilirsiniz; tersi, yani hareketli bir çıktıdan kararlı giriş konumlarını yeniden inşa etmek mümkün değildir
Sizi Koruyan Kurallarla Silme ve Değiştirme
Bir değiştirme, ham içerik akışı baytlarıdır ve sözdizimlerinden siz sorumlusunuz. Bunların etrafındaki korumalar; toplam değiştirme baytları üzerindeki bütçe, çakışmama gerekliliği ve kabul edilmeden önce sonucu yeniden ayrıştıran isteğe bağlı çıktı doğrulamasıdır:
procedure TWatermarkStripper.HandleOperator(Sender: TObject;
var EventData: THPDFContentOperatorEventData);
begin
EventData.Action := coaKeep;
if EventData.Phase <> covpOperator then
Exit;
// Filigran formunu boyayan operatörleri düşür
if (EventData.OperatorName = 'Do') and OperandIsWatermark(EventData) then
EventData.Action := coaDelete
// Başıboş bir rengi kurumsal griye normalize et
else if EventData.OperatorName = 'rg' then
begin
EventData.Replacement := TEncoding.ANSI.GetBytes('0.2 0.2 0.2 rg');
EventData.Action := coaReplace;
end
// Anlamadığımız bir şeyle karşılaşırsak tüm düzenlemeyi reddet
else if EventData.OperatorName = 'BI' then
EventData.Action := coaReject;
end;
var
Options: THPDFContentOperatorVisitOptions;
begin
Options := THPDFContentOperatorVisitOptions.Default;
Options.ValidateOutput := True; // kabul etmeden önce yeniden ayrıştır
Options.MaxReplacementBytes := 64 * 1024;
Pdf.OnContentOperator := HandleOperator;
if Pdf.VisitLoadedPageContentOperators(PageIndex, True, Options, nil, Stats) then
if Stats.Modified then
Pdf.SaveLoadedDocument('cleaned.pdf');
end;
Eylem kümesi bir nedenden ötürü iki çıkış içerir. coaStop, dolaşmayı sonlandırır ve o ana kadar karar verilenleri korur; bu, aradığınızı bulduğunuzda doğrudur. coaReject, tüm ziyareti terk eder ve sayfayı dokunulmamış bırakır; bu, yeniden yazma kurallarınızın kapsamadığı bir yapıyla karşılaştığınızda doğrudur. Satır içi görüntüler klasik bir örnektir: ikili yükleri, bir renk normalleştiren ziyaretçinin etrafında düzenleme yapması gereken bir şey değildir
İstatistikleri Okumak ve Dolaşmanın Durduğu Yer
Durum alanı; tamamlanmayı durdurmadan, reddetmeden, geçersiz girişten, aşılan bir sınırdan, geçersiz çıktıdan ve bir ziyaretçi hatasından ayırır. Bunlar farklı sorunlardır: geçersiz çıktı, değiştirme baytlarınızın yeniden ayrıştırılamadığı anlamına gelirken geçersiz giriş, kaynak akışın zaten bozuk olduğu ve hiçbir düzenlemenin denenmediği anlamına gelir
Sayaçlar, bir denetimi kendi kendini kontrol eden hale getirir. VisitedOperatorCount, KeptOperatorCount, DeletedOperatorCount ve ReplacedOperatorCount ile toplanmalıdır ve maksimum derinlik rakamları, sayfanın daha yakından bakmaya değecek kadar derin iç içe geçip geçmediğini söyler. SourceBytes'ın OutputBytes ile karşılaştırılması, düzenlemenizin boyut etkisini tek bir sayıda verir
Yaygın görevler için bir ziyaretçi yazmayı hiç gerektirmeyen daha üst düzey yollar vardır. İçeriği kalıcı olarak kaldırmak, gerçek redaksiyonun ihtiyaç duyduğu kaynak temizliğiyle birlikte, yüklenmiş belgelerde redaksiyon ve sayfa dikişi başlığında ele alınmıştır. Görünür metni değiştirmek, mevcut bir PDF'de arama ve değiştirme başlığında ele alınmıştır. Kuralınız metinsel değil yapısal olduğunda veya hiçbir mevcut raporun yanıtlamadığı bir denetime ihtiyaç duyduğunuzda operatör ziyaretçisine başvurun
İçerik akışı ziyareti, çıkarma ve yeniden yazma, Delphi ve C++Builder'da aynı yüklenmiş belge modeli üzerinde çalışır; eksiksiz özellik listesi HotPDF Delphi PDF bileşeni sayfasında bulunur