HotPDF Componentte THotPDF.Resolution çizim birimini tanımlar: her X ile Y koordinatı, her kenar boşluğu, SetFonta geçilen boyut ve TextWidth ile GetWideTextWidthin sonuçları 1/Resolution inç olarak ölçülür. THPDFPage.Width ile Height onu izlemez ve puantoda kalır; düzen sınırları bu yüzden salt okunur UserWidth ile UserHeightten gelmelidir. Resolutiona dokunmanın sıradan sebebi bir porttur: 1/96 ya da 1/144 inçte düşünen bir rapor motoru, her çağrı noktasına bir dönüşüm katsayısı koymaktansa PDF tarafı aynı birimi konuştuğunda taşınması kolaydır. Bu iyi çalışır; hangi sayıların yeni birime taşındığını, hangilerinin geride kaldığını bildiğiniz sürece
THotPDF.Resolution aslında neyi değiştirir?
THotPDF.Resolution yalnızca HotPDFin geçtiğiniz sayıları nasıl okuduğunu değiştirir; yazdığı PDF aynıdır. Setter iki satırdır: SetResolution değeri saklar ve DocScale := Value / 72 set eder. O andan itibaren XProjection ile YProjection her koordinatı content streamine girerken DocScalee böler ve SetFont boyutu aynı şekilde bölüp kaydeder. PDF user space varsayılanı 1/72 inçtir (ISO 32000-1 §8.3.2.3); varsayılan Resolution 72de izdüşüm kimliktir, 144te bir çizim birimi yarım puntodur. /UserUnit girdisi yazılmaz. O sayfa attributü, PDF 1.6da eklenen, HotPDFin THPDFPage.SetUserUnit olarak açtığı ayrı bir şeydir. TextOut rehberlerinden gelenleri yakalayan bir ayrıntı: sayfa koordinatları sol üst köşeden başlar ve Y aşağı doğru büyür, çünkü YProjection ölçeklenmiş Yden MediaBox üstünü çıkarır; bu her Resolutionda geçerlidir
var
Pdf: THotPDF;
Page: THPDFPage;
Margin: Single;
Title: WideString;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'invoice.pdf';
Pdf.Resolution := 144; // 1 çizim birimi = 1/144 inç
Pdf.BeginDoc;
Page := Pdf.CurrentPage; // A4: Width = 595, UserWidth = 1190
Margin := 144; // çizim birimlerinde bir inç
Page.SetFont('Arial', [fsBold], 28); // 28/144 inç, 14 ptlik bir font
Title := 'INVOICE 2026-0417';
// Sayfa kenarına aynı birimle ölçerek sağa hizala
Page.TextOut(Page.UserWidth - Margin - Page.GetWideTextWidth(Title),
Margin, 0, Title);
Page.SetLineWidth(2); // 1 ptlik çizgi
Page.MoveTo(Margin, Margin + 48);
Page.LineTo(Page.UserWidth - Margin, Margin + 48);
Page.Stroke;
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Resolution 144te Page.Width koordinatlarımla neden uyuşmaz?
THPDFPage.Width ile Height, belge Resolutionı ne olursa olsun sayfayı puantoda bildirir; sizin koordinatlarınız ise 1/Resolution inçtedir, dolayısıyla 144te sayfa gerçekte olduğunun yarı genişliğinde görünür. Bir A4 sayfası Resolution 72de Width = 595 ve Height = 842 okur ve 144te hâlâ 595 ile 842 okur; oysa sağ kenar aslında X = 1190dadır. v2.766.0da eklenen UserWidth ile UserHeight Width * DocScale döndürür; yani çizim yaptığınız birimdeki sayfa boyutunu. Onlar var olmadan önce kütüphane ikisini içeride karıştırıyordu ve Resolution 144teki belirtiler dramatikti: paragraflar her karakterden sonra sarılıyordu, THPDFTable.Render her satırı yeni bir sayfaya itiyordu, HTML importerı ile XFA flattenerı içeriklerini yarım boyutta çiziyor, düzleştirilmiş form sol üst köşeye sıkışıyordu. Paragraf düzeni, tablo renderi, HTML importu, EMF ortalaması, WMF sayfa kırpması ve düzen tanılamaları artık hepsi user-unit boyutunu okur. Sizin düzen kodunuz da okumalı: bir çizim koordinatıyla karşılaştıran her şey (sağ kenar boşluğu, sayfa sonu testi, ortalama hesabı) UserWidth ile UserHeightte durur, asla Width ile Heightte değil
Tuzak bir: Width ya da Height atamak sayfayı puntoya çevirir
Page.Width ya da Page.Height set etmek sayfayı sessizce UserDefinede çevirir ve UserDefined bir sayfa DocScalei tamamen yok sayar; yani sonrasında üzerine çizdiğiniz her şey 1/Resolution inçte değil puantodadır. Setter eskidir ve tasarım gereği punto alır; anlamının olduğu gibi bırakılmasının sebebi budur. UserDefined bir sayfanın izdüşümü düz X + MinXdir ve SetFont boyutu değiştirmeden saklar. Resolution 144te sonuç, içeriği bir önceki sayfanınkinden iki kat büyük çıkan bir sayfadır. Kütüphane bu hatayı kendisi de tam olarak yaptı: paragraf devam sayfaları önceki sayfanın boyutunu Width üzerinden kopyalıyordu ve her taşma sayfası puntoya geçiyordu. O sayfalar artık Size, Orientation ve sayfa Resolutionını kopyalar ve yalnızca özgün sayfa hâlihazırda UserDefinedse Width ile Heighte döner
İhtiyacınıza göre iki çıkış yolu var. Standart bir sayfa işinizi görüyorsa Page.Size ile Page.Orientation set edin ve Resolution biriminizde çizmeye devam edin. Gerçekten özel bir sayfa boyutu gerekiyorsa bunun bir punto sayfası olduğunu kabul edip puantoda çizin; orada UserWidth Widthe eşittir, dolayısıyla her zaman UserWidth okuyan düzen kodu her iki sayfa türünde de çalışır. Unit test bunu çiviler: Resolution 144te bir A4 sayfası 1190 UserWidth bildirir; Width := 500 ile Height := 400 sonrasında 500 ile 400 bildirir. Yüklenen sayfalar aynı davranır, çünkü mevcut bir PDFden yeniden kurulan bir sayfa puantodaki MediaBoxını bilir ve puantoda çizer. Bu belgenin oluşturduğu sayfalar, CurrentPageNumber üzerinden uzaklaşıp geri döndüğünüzde kendi birimlerini korur; v2.766.26dan beri durum budur
Tuzak iki: font boyutları neden yarı boyutta çıkar?
Punto olarak başlayan bir font boyutu Resolution 144te yarı boyutta çıkar, çünkü SetFont boyut argümanını çizim birimi sayar ve saklamadan önce puntoya çevirir. Dahili olarak SetFont, mevcut font objesine ASize / DocScale * DPI saklar; saklanan değer her zaman puntodur. Kütüphane buna iki kez takıldı: WideTextOutBoxExdeki font yedeği ile paragraf devam sayfası ikisi de o saklanan punto değerini SetFonta geri veriyordu; metot ikinci kez ölçekleyip metni yarıya indiriyordu. Sizin kodunuz saklanan boyutu okuyamaz ama aynı hata, başka bir yerden gelen bir punto değeri SetFonta ulaştığında ortaya çıkar: bir VCL formdan TFont.Size, bir rapor tanımındaki boyut, bir CSS pt uzunluğu. Önce çevirin ve katsayıya sayfanın kendi Resolutionını da UserDefined durumunu da dahil edin; metafile oynatma, sayfa Canvasını oynatırken tam olarak bunu yapar (o yol için HotPDF EMF ve WMF vektör grafiklerini nasıl import eder yazısına bakın):
// Mevcut sayfada punto başına çizim birimi. HotPDFin izdüşümünü
// yansıtır: Width/Height ile boyutlanmış sayfada 1, aksi hâlde
// (document Resolution / 72) * (page Resolution / 72)
function UnitsPerPoint(Pdf: THotPDF): Single;
begin
if Pdf.CurrentPage.Size = UserDefined then
Result := 1
else
Result := (Pdf.Resolution / 72) * (Pdf.CurrentPage.Resolution / 72);
end;
procedure SetFontFromVcl(Pdf: THotPDF; Font: TFont);
begin
// TFont.Size puantodadır; SetFont çizim birimi bekler
Pdf.CurrentPage.SetFont(AnsiString(Font.Name), Font.Style,
Font.Size * UnitsPerPoint(Pdf));
end;
Kütüphane aynı kuralı kendi punto sabitlerine uygular. Her yeni sayfanın başladığı 12 puntoluk font artık dahili punto-birim katsayısıyla çarpılır; yani her Resolutionda 12 puntodur. Kenar boşlukları, etiket boyutları ve çizgi kalınlıkları hâlihazırda sabit punto olan DrawChart artık ölçek geçici olarak 1e set edilmiş hâlde çalışır. Bilinçli olarak çizim birimlerinde kalan şey, DrawQRCode modül boyutu ve varsayılan tablo font boyutu gibi public parameter varsayılanlarıdır: onlar API sözleşmesinin parçasıdır, dolayısıyla Resolution 144te 72de anlamlarının yarısını ifade eder. Raporları bir şablondan boyutlandırıyorsanız HotPDFte font ve imageli rapor çıktısı rehberi o değerlerin genelde nereden geldiğini kapsar
Bir düzenin Resolutiondan bağımsızlığını nasıl doğrularsınız?
En güvenilir kontrol bayt karşılaştırmasıdır: aynı sayfayı Resolution 72de ve koordinatların ve boyutların hepsi iki katına çıkarılmış hâlde 144te render edin; sıkıştırılmamış content streamler özdeş olmalıdır. Her iki koşu da izdüşüm sonrası aynı punto değerlerine düşer; herhangi bir fark, dönüşümü atlayan bir değerdir. HotPDF test takımı paragrafları, tabloları, HTML importunu, XFA düzleştirmesini, yayları, metafileleri ve imageleri böyle kontrol eder. Aynı teknik, neredeyse hiç donanım olmadan kendi rapor kodunuz için de işler:
procedure RenderPage(const FileName: string; Res: Integer; K: Single);
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.AutoLaunch := False;
Pdf.Compression := cmNone; // okunabilir content streamler
Pdf.FileName := FileName;
Pdf.Resolution := Res;
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 10 * K);
Pdf.CurrentPage.TextOut(36 * K, 36 * K, 0, 'Line 1');
Pdf.CurrentPage.Rectangle(36 * K, 60 * K, 200 * K, 40 * K);
Pdf.CurrentPage.Stroke;
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
// RenderPage('r72.pdf', 72, 1) ve RenderPage('r144.pdf', 144, 2)
// bayt olarak özdeş sayfa content streamleri üretmeli
Sayı taşıyan operatörleri kontrol edin: Td, Tm, Tf, re, w ve TJ dizileri. Dosya düzeyi baytlar yine de oluşturma tarihiyle /IDde farklılaşır; bu yüzden bütün dosyaları değil streamleri karşılaştırın. Bir uyuşmazlık neredeyse her zaman yukarıdaki iki tuzağın birine işaret eder: Width üzerinden yeniden boyutlanmış bir sayfa ya da doğrudan SetFonta geçilen bir punto değeri. Çizim çağrılarının kendisinde yeniyseniz boyut, stil ve rotasyon için HotPDF TextOut rehberiyle başlayın; düzeniniz UserWidth okumaya başlayınca geri gelip Resolutionı bir kez değiştirin. Tam API ayrıntıları ve deneme indirmeleri HotPDF Delphi PDF component sayfasındadır