İçeriğe geç
getnextpdf.com

CJK ve Arapça PDF'lerde kopyala-yapıştırmayı doğru hale getirin

Çince, Japonca, Korece (CJK) ve Arapça metin içeren ve bu metnin özgün mantıksal karakterler olarak kopyalanıp yapıştırılmasını sağlayan bir Portable Document Format (PDF) dosyası oluşturun. Motor, her glifi bir /ToUnicode CMap aracılığıyla Unicode’a eşler, sonucu Normalization Form Compatibility Composition (NFKC) ile kanonikleştirir ve şekillendirilmiş veya harf aralıklı dizileri /ActualText taşıyan bir /Span içine sarar. Yazı tiplerini kaydedip içeriği yazmanız yeterlidir; çıkarma doğru kalır. Çıkarmayı PyMuPDF ile değil, pdftotext/Poppler ile doğrulayın; veraPDF, çıkarmayı değil, PDF/Universal Accessibility 2 (PDF/UA-2) uyumluluğunu doğrular.

Terminal window
composer require nextpdf/core

Noto Sans CJK gibi bir CJK yazı tipi ve Arabic Presentation Forms-B bloğunu kapsayan karakter eşlemesine sahip, Arapça destekli bir yazı tipi (örneğin Noto Naskh Arabic) kaydedin. Yalnızca gömme lisansına sahip olduğunuz yazı tiplerini gömün.

Bir içerik akışındaki glif kodları Unicode değildir. Bir /ToUnicode CMap, okuyucunun metni çıkarabilmesi için her kodu yeniden Unicode’a eşler (ISO 32000-2 §9.10). Motor, bu değerleri Unicode UAX #15 tarafından tanımlandığı şekilde Normalization Form Compatibility Composition (NFKC) ile kanonikleştirir. Bir CJK Compatibility Ideograph ve bir Arapça sunum biçimi temel karakterlerine eşlenir; böylece arama ve kopyalama işlemleri, bir uyumluluk kod noktası yerine kanonik metin döndürür.

İki durum /ToUnicode’dan fazlasını gerektirir: harf aralıklı Latin ve şekillendirilmiş sağdan sola Arapça. Motor bunları aralıklı veya yeniden sıralanmış glifler olarak çizer; bu nedenle tek başına glif sırası mantıksal dizeyi geri kazanamaz. Motor, her diziyi, sarmalanan içeriğin tam yerine geçen /ActualText taşıyan bir /Span işaretli içerik dizisi içine sarar (ISO 32000-2 §14.9). /ActualText’e uyan çıkarıcılar mantıksal dizeyi döndürür.

SembolKonumRol
FontRegistry::register(string $fontFile, string $alias = ''): FontInfoNextPDF\Typography\FontRegistryCJK ve Arapça yazı tipi yüzlerini kaydeder.
DocumentFactory::create(): DocumentNextPDF\Core\DocumentFactoryKayıt defterinizi kullanan bir belgeyi oluşturur.
Document::writeHtml(string $html): staticNextPDF\Core\Concerns\HasTextOutputÇok dilli içeriği işler.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\FontRegistry;
$fonts = new FontRegistry();
$fonts->register(__DIR__ . '/NotoSansCJK-Regular.ttf', alias: 'CJK');
$fonts->register(__DIR__ . '/NotoNaskhArabic-Regular.ttf', alias: 'Arabic');
$doc = (new DocumentFactory($fonts, new ImageRegistry(maxCacheBytes: 0)))->create();
$doc->addPage();
$doc->writeHtml(
'<p style="font-family: \'CJK\';">PDF 2.0 引擎 — 量子</p>'
. '<p style="direction: rtl; font-family: \'Arabic\';">فاتورة</p>'
);
$doc->save(__DIR__ . '/multilingual.pdf');
Terminal window
pdftotext multilingual.pdf - | head
# Extracts the logical text: "PDF 2.0 引擎 — 量子" and the logical Arabic "فاتورة",
# not compatibility code points or reversed presentation forms.

Bu bağımsız örnek, belgeyi etiketler, harf aralıklı bir başlık ekler ve test düzeneğinin yoluna yazar.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\FontRegistry;
$fonts = new FontRegistry();
$fonts->register(__DIR__ . '/NotoSansCJK-Regular.ttf', alias: 'CJK');
$fonts->register(__DIR__ . '/NotoNaskhArabic-Regular.ttf', alias: 'Arabic');
$doc = (new DocumentFactory($fonts, new ImageRegistry(maxCacheBytes: 0)))->create();
$doc->setTitle('Multilingual extraction');
$doc->enableTaggedPdf('en');
$doc->addPage();
$html = <<<'HTML'
<h1 style="font-family: 'CJK'; letter-spacing: 3px;">CODE WORD</h1>
<p style="font-family: 'CJK';">中文 · 日本語 · 한국어 · 量子 (compatibility ideograph)</p>
<p style="direction: rtl; font-family: 'Arabic';">المبلغ الإجمالي 380.00</p>
HTML;
$doc->writeHtml($html);
$out = getenv('NEXTPDF_OUT');
$doc->save($out !== false ? $out : __DIR__ . '/multilingual-copy-paste-extraction.pdf');
echo "Wrote the multilingual PDF\n";

Oluşturulan çıktı üzerinde pdftotext çalıştırın. Harf aralıklı başlık, araya hiçbir boşluk eklenmeden CODE WORD olarak çıkar; CJK satırı temel karakterler olarak çıkar ve Arapça satır mantıksal dize olarak çıkar.

  • Çıkarmayı PyMuPDF ile değil, pdftotext ile doğrulayın. PyMuPDF’in ham metin modu, satır içi /ActualText’i yok sayar ve görsel glifleri döndürür; bu nedenle doğruluğu olduğundan düşük gösterebilir. Poppler (pdftotext), /ActualText’e uyar; veraPDF, çıkarmayı değil, PDF/UA-2 uyumluluğunu doğrular.
  • Çıkarma /ToUnicode gerektirir. Yazı tiplerini, yazıcı /ToUnicode CMap’i üretecek şekilde kaydedin ve gömün. Gömülmemiş, standart olmayan bir yazı tipi bir Unicode eşlemesini garanti edemez.
  • /ActualText, şekillendirilmiş ve harf aralıklı dizileri kapsar. Düz, şekillendirilmemiş ve aralıksız metin yalnızca /ToUnicode ile doğru biçimde çıkarılır; /Span sarmalayıcı, aralıklı veya yeniden sıralanmış dizileri korur.
  • Etiketli HTML tabloları PDF/UA-2 denetimlerinden geçer. Çıkarma doğrudur ve etiketli bir HTML <table> artık veraPDF --flavour ua2 denetiminden hiçbir başarısızlık olmadan geçer; bkz. Erişilebilirlik.

/ToUnicode CMap’i ve /Span sarmalayıcılarını oluşturmak, glif sayısıyla doğrusal olarak ölçeklenir. Bu tarifin bütçesi wall_ms: 1500, peak_mb: 96 şeklindedir.

Çıktı boyutunun sınırlı kalması için kullanıcı tarafından sağlanan çok dilli dizelerin uzunluğunu doğrulayın. /ToUnicode oluşturucusu, vekil yarımları ve kod alanının dışındaki kodları reddeder; böylece hatalı biçimlendirilmiş bir eşleme bozuk bir çıkarmaya kaynaklık edemez. Motor hiçbir betik çalıştırmaz; yerel yazı tipleri için de hiçbir uzak kaynak getirmez.

İfadeBelirtimMadde
Bir /ToUnicode CMap, çıkarma için karakter kodlarını Unicode’a eşler.ISO 32000-2§9.10
/ActualText, sarmalanan içeriğin tam yerine geçer.ISO 32000-2§14.9
NFKC, uyumluluk ayrıştırmasının ardından gelen kanonik bileşimdir.Unicode UAX #15§1.2

Uygulanamaz.