İçeriğe geç

ContentStream: PDF içerik akışı yayımlayıcısı

ContentStream modülü, Portable Document Format (PDF) işaretli içerik işleçlerini yayar. Yapı etiketlerini ve yapıntıları açıp kapatır, iç içe geçme derinliğini izler ve işleç arabelleğini döndürür.

Terminal window
composer require nextpdf/core:^3

ContentStreamBuilder, bu modüldeki tek sınıftır. Bir sayfa içerik akışının işaretli içerik katmanını oluşturur. Bir içerik akışı, sayfa içeriğini bir işleç dizisi olarak kodlar — ISO 32000-2 §8. Oluşturucu daha sonra bu içeriğin çevresine işaretli içerik işleçleri yayar.

append(), ham işleç baytlarını aynen ekler. Oluşturucu bu girdiyi kaçışlamaz. Girdinin geçerliliğinden siz sorumlusunuz. HTML işlem hattı ve Graphics modülü kendi işleçlerini araya eklemek zorunda olduğunda bu sınırı kullanın.

beginTag(), yapı etiketli bir dizi açar. ISO 32000-2 §14.6 uyarınca bir BDC işleci ve buna ait bir MCID özellik listesi yayar. endTag(), eşleşen EMC işlecini yayar. Oluşturucu, iç içe geçme derinliğini izler. Açık bir dizi yokken endTag() çağrılırsa PageLayoutException fırlatır; dengesiz bir EMC yazmaz.

beginArtifact(), bir yapıntı dizisi açar. ISO 32000-2 §14.8.2.2 uyarınca yapı ağacının dışında kalması gereken sayfalama süslemeleri — üstbilgiler, altbilgiler, sayfa numaraları ve çizgiler — için yapıntıları kullanın. Alt tür şu dört ISO değerinden biridir: Pagination, Layout, Page veya Background. Tür güvenli ArtifactSubtype enum’unu tercih edin. Dize aşırı yüklemesi enum’a göre doğrulanır; bu nedenle standart dışı bir değer hemen hata verir.

relabelTag(), daha önce yayılmış bir etiketi yerinde yeniden yazar. finish(), tam arabelleği döndürür ve işaretli içerik dengesizse hata fırlatır. drain(), artımlı akış için denge denetimi yapmadan o ana kadarki arabelleği döndürür. peek(), arabelleği tüketmeden döndürür. reset(), durumu temizler.

YöntemİmzaRol
append()append(string $raw): voidHam işleç baytlarını aynen ekler (kaçışlama yok)
beginTag()beginTag(string $structType, int $mcid): voidBir BDC yapı dizisi açar
endTag()endTag(): voidEn içteki diziyi şu işleçle kapatır: EMC
beginArtifact()beginArtifact(ArtifactSubtype|string $type): voidBir yapıntı dizisi açar
endArtifact()endArtifact(): voidEn içteki yapıntıyı kapatır
getMarkedContentDepth()getMarkedContentDepth(): intGeçerli iç içe geçme derinliğini döndürür
relabelTag()relabelTag(string $old, string $new, int $mcid): voidYayılmış bir etiketi yerinde yeniden yazar
finish()finish(): stringTam arabelleği döndürür; dengesizlik varsa hata fırlatır
drain()drain(): stringArabelleği denge denetimi yapmadan döndürür
peek()peek(): stringArabelleği tüketmeden döndürür
reset()reset(): voidTüm durumu temizler

Tam PHPDoc tablosunu oluşturmak için composer docs:generate-api-php -- --module=ContentStream komutunu çalıştırın.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\ContentStream\ContentStreamBuilder;
$builder = new ContentStreamBuilder();
$builder->beginTag('P', mcid: 0);
$builder->append("BT /F1 12 Tf 72 720 Td (Hello) Tj ET\n");
$builder->endTag();
$pageContent = $builder->finish();

Bir paragrafı bir yapı etiketiyle, bir altbilgiyi de bir yapıntıyla sarmalamak için bu kalıbı kullanın. Bu kalıp, arabelleği drain() ile artımlı olarak akıtır.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Accessibility\ArtifactSubtype;
use NextPDF\ContentStream\ContentStreamBuilder;
$builder = new ContentStreamBuilder();
$builder->beginTag('H1', mcid: 0);
$builder->append($titleOperators);
$builder->endTag();
$builder->beginArtifact(ArtifactSubtype::Pagination);
$builder->append($footerOperators);
$builder->endArtifact();
if ($builder->getMarkedContentDepth() !== 0) {
throw new RuntimeException('Unbalanced marked content before flush.');
}
$chunk = $builder->drain();
  • append() girdiyi kaçışlamaz. Yalnızca geçerli işleç baytlarını geçirin. Oluşturucu, çağıran tarafa güvenir.
  • endTag() ve endArtifact(), alt taşmada hata fırlatır. Açık olmayan bir diziyi asla kapatmayın.
  • finish() dengeyi denetler ve derinlik sıfır değilse hata fırlatır. drain() denetlemez. drain() işlevini yalnızca artımlı akış için kullanın.
  • Derinlik sayacı, etiketleri yapıntılardan ayırt etmez. EMC, her iki türden de en içteki diziyi kapatır. Dizileri kesin bir sırayla iç içe geçirin.
  • Dize aşırı yüklemesi kullanıldığında beginArtifact() enum’a göre doğrulanır. Standart dışı bir alt tür, çıktıda değil çağrı sırasında hata verir.
  • relabelTag(), yayılmış bir etiketi yeniden yazar. Etiketi yaymak için kullandığınız mcid değerinin aynısını kullanın.

O(arabellek) yeniden yazma gerçekleştiren relabelTag() dışında her işlem O(1) dize eklemedir. Modül, bir dize arabelleği ve bir tam sayı derinlik sayacı tutar. Hiçbir ayrıştırma yapmaz ve yalnızca arabelleği ayırır. Referans iş yükü bütçesi 1500 ms duvar saati ve 64 MB tepe değeridir. Bu modül, bu değerlerin çok altında kalır.

append(), güven sınırıdır. Oluşturucu baytları aynen yazar; bu nedenle yukarı akış kodu, bir hazır dize işlecine ulaşan her dizeyi kaçışlamalıdır. Standart kaçışlayıcı PdfStringEscaper::escapeLiteral() işlevidir (ADR-015). Kaçışlanmamış kullanıcı metnini asla append() üzerinden geçirmeyin. endTag(), endArtifact() ve finish() işlevlerindeki denge denetimleri, hatalı biçimlendirilmiş bir işaretli içerik ağacının Writer’a ulaşmasını engeller. Belge tehdit modeli için /modules/core/security/ sayfasına bakın.

Modül, ISO 32000-2 ile tutarlı işaretli içerik işleç yapıları yayar: BDC/EMC çiftleri (§14.6 uyarınca, bir MCID özellik listesiyle) ve §14.8.2.2 uyarınca yapıntı dizileri. Bunlar uygulamaya ilişkin gerçeklerdir. Kanıt, src/ContentStream/ContentStreamBuilder.php, src/Accessibility/ArtifactSubtype.php enum’u ve tests/Unit/ContentStream/ContentStreamBuilderMarkedContentBalanceCoverageTest ile birlikte ContentStreamBuilderRelabelTagInvariantTest testidir. Bunlar, uçtan uca PDF/UA-2 veya PDF 2.0 uygunluğu iddiası değildir. Bu işleçlerin yer aldığı etiketli PDF yapısını harici bir kahin doğrular: tests/Integration/Accessibility/VeraPdfUa2GoldenTest, oluşturulmuş bir sınama düzeneğini PDF/UA-2 profili için veraPDF’ye karşı denetler. Bu kahin testi veraPDF ikili dosyası mevcut olmadığında atlanır; bu nedenle isteğe bağlı bir geçittir. Bu modül için koşulsuz uygunluk öne sürmek yerine “işaretli içerik yapıları üretir; PDF/UA-2 uygunluğu veraPDF tarafından doğrulanır” ifadesini kullanın.