Dlaczego tekst w pliku PDF nie jest tak naprawdę tekstem
W skrócie
Dział zatytułowany „W skrócie”Kiedy czytasz plik PDF, widzisz słowa. Plik nie zawiera słów. Zawiera instrukcje namalowania kształtów we współrzędnych, a te kształty akurat wyglądają jak litery. Przepaść między tym, co PDF rysuje, a tym, co oznacza, jest powodem, dla którego strona może wyglądać nienagannie, a mimo to dać się skopiować jako nonsens. Ta strona dotyczy tej przepaści oraz niewielkiego, osobnego odwzorowania, które ją zamyka.
Dlaczego to ma znaczenie
Dział zatytułowany „Dlaczego to ma znaczenie”Wszystko, co robisz z plikiem PDF jako z tekstem — zaznaczanie, kopiowanie,
wyszukiwanie, indeksowanie do wyszukiwania, odczytywanie na głos czytnikiem
ekranu — zależy od odzyskania znaków, których plik nigdy bezpośrednio nie
przechował. Jeśli to odzyskiwanie zawiedzie, awaria jest niewidoczna. Strona
nadal się renderuje. Nikt nie zauważa, dopóki ktoś nie skopiuje akapitu do
wiadomości e-mail i nie dostanie □□□□, albo nie przeszuka 400-stronicowej
umowy w poszukiwaniu klauzuli, która ewidentnie tam jest, i nie znajdzie
niczego.
To kosztowna klasa błędów właśnie dlatego, że przetrwa każdą recenzję wizualną. Nie ma nic do zobaczenia. Dokument wygląda wiarygodnie i jest — dla potrzeb maszyny — niemy.
Wersja skrócona
Dział zatytułowany „Wersja skrócona”- PDF rysuje glify — kształty wizualne dobierane za pomocą numerycznych kodów do czcionki — a nie znaki Unicode.
- Ten sam kształt może oznaczać różne znaki, a ten sam znak może być rysowany przez różne glify. Wygląd i znaczenie są z założenia rozdzielone.
- Aby odzyskać tekst, czytnik przebiega ścieżkę wyświetlania wstecz: od kodu do
znaku. CMap
/ToUnicodeczcionki to tablica wyszukiwania dla tego kroku wstecznego (Spec: ISO 32000-2, §9.10ISO 32000-2 §9.10). - Brak
/ToUnicodealbo błędny/ToUnicodeoznacza zniekształcone kopiowanie i wklejanie oraz nieudane wyszukiwanie — przy stronie wciąż idealnej co do piksela. - To problem znaczenia. To, czy glif wygląda poprawnie, jest osobnym problemem
wyglądu, omówionym w
Czcionki: ta trudna część. NextPDF
emituje poprawny
/ToUnicode, dzięki czemu obieg w obie strony jest wierny.
Jak podchodzi do tego NextPDF
Dział zatytułowany „Jak podchodzi do tego NextPDF”Zacznij od tego, jak tekst w ogóle trafia na stronę. Strumień zawartości nie
mówi „napisz słowo file”. Wybiera czcionkę, a następnie podaje ciąg kodów
operatorowi wyświetlania tekstu (Spec: ISO 32000-2, §9ISO 32000-2 §9).
Każdy kod jest indeksem — pozycją w programie czcionki — a czcionka zamienia ten
indeks w obrys glifu i go maluje. Kod 70 to nie znak F. To „slot 70 w tej
czcionce”, a slot 70 akurat mieści krzywą w kształcie F. Wybierz inną czcionkę,
a slot 70 mógłby być płatkiem śniegu.
Kod znaczy więc coś tylko względem kodowania swojej czcionki. Dla prostej czcionki to kodowanie jest w przybliżeniu jednym bajtem na glif. Dla pism, które potrzebują tysięcy glifów — CJK lub dowolnego dokumentu w pełnym Unicode — to za mało miejsca, więc PDF sięga po czcionkę złożoną (Type 0) (Spec: ISO 32000-2, §9.7ISO 32000-2 §9.7). Czcionka złożona odczytuje wielobajtowe kody przez CMap, zamienia je w CID (identyfikatory znaków) i odwzorowuje CID-y na glify. To eleganckie pośrednictwo, które pozwala jednej czcionce zaadresować ogromny zestaw glifów. Jest to też jeszcze jedno miejsce, w którym trop od „tego, co pokazane” do „tego, co oznacza” może się urwać.
Teraz przebiegnij to wstecz. Aby wyodrębnić tekst, czytnik bierze kody, które znajdzie w strumieniu zawartości, i musi odzyskać znaki (Spec: ISO 32000-2, §9.10ISO 32000-2 §9.10). Kodowanie, które narysowało glif, szło od znaku do glifu; ekstrakcja potrzebuje od kodu glifu do znaku, a ten kierunek nie ma gwarancji odwracalności. Czcionka będąca podzbiorem mogła przenumerować swoje glify. CID-y czcionki złożonej mogą być prywatne. Kształt na stronie nie niesie wewnętrznego znaczenia Unicode.
Rozwiązaniem jest dostarczenie wraz z czcionką odwzorowania wstecznego. Tym
odwzorowaniem jest CMap /ToUnicode: dla każdego kodu używanego przez
dokument zapisuje wartość (lub wartości) Unicode, którą ten kod reprezentuje.
Z nim ekstrakcja jest czystym wyszukiwaniem. Bez niego czytnikowi pozostaje
zgadywanie na podstawie kodowań czcionek i heurystyk — a zgadywanie jest
dokładnie tym, gdzie fi staje się znakiem zapytania.
- Your charactersThe Unicode text you set, for example the word 'file'.
- Encoding → codesThe font's encoding turns characters into numeric codes; a composite font routes them through a CMap to CIDs.
- Codes → glyphsEach code selects a glyph outline, which is painted to the page. This is the part you see.
- Extraction reverses itA reader reads the codes back and looks each one up in /ToUnicode to recover Unicode.
- Text againWith a correct /ToUnicode, copy, search, indexing, and screen readers all get the original characters back.
NextPDF zapisuje odwzorowanie wsteczne rutynowo. Gdy osadza czcionkę złożoną,
emituje potomka CIDFontType2, rodzica Type0 oraz CMap /ToUnicode, dzięki
czemu kody odwzorowują się z powrotem na Unicode — to praca nad kodowaniem
opisana w Czcionki: ta trudna część. Warto
tu wyodrębnić dlaczego: strumień /ToUnicode nie służy sprawieniu, by strona
wyglądała poprawnie. Glify już bez niego wyglądają poprawnie. To jedyny artefakt,
który utrzymuje tekst możliwym do wyodrębnienia.
Praktyczny przykład
Dział zatytułowany „Praktyczny przykład”Najsłynniejszym miejscem, w którym to się ujawnia, jest ligatura fi. Wiele
czcionek rysuje f i i jako jeden połączony glif, ponieważ kropka nad i
koliduje z haczykiem f. Na stronie to jeden kształt, narysowany jednym kodem.
Pytanie brzmi, co się stanie, gdy go skopiujesz.
% A /ToUnicode entry that maps the single ligature code to TWO characters,% so selecting the 'fi' glyph copies out as 'f' then 'i' — not one mystery box.1 beginbfchar<0085> <00660069> % code 0x85 -> U+0066 'f' U+0069 'i'endbfcharTen jeden wpis to różnica między wyszukaniem słowa „file”, które trafia, a
wyszukaniem słowa „file”, które po cichu mija każde wystąpienie wyrenderowane z
ligaturą. Odwzoruj kod ligatury na dwuznakową sekwencję f + i, a słowo da się
wyszukać i skopiować. Pozostaw je bez odwzorowania, a strona wciąż pokazuje file
idealnie, podczas gdy tekst po cichu nie mówi niczego, co maszyna mogłaby
odczytać.
Dlatego „fi” może wyodrębnić się jako jeden znak lub dwa i dlatego ta różnica nie
jest przypadkowa — jest tym, co odwzorowaniu /ToUnicode kazano powiedzieć.
Poprawne odwzorowanie rozkłada ligaturę z powrotem na jej znaki. NextPDF emituje
dokładnie taki wpis, dzięki czemu ligatura na stronie to dwie zwykłe litery w
schowku.
Powszechne nieporozumienie
Dział zatytułowany „Powszechne nieporozumienie”Pułapka, nazwana: „tekst się renderuje, więc tekst jest w porządku”.
Renderowanie i ekstrakcja to różne mechanizmy odczytujące różne dane.
Renderowanie idzie ścieżką od kodu do glifu i jest tym, co sprawdzają twoje oczy.
Ekstrakcja idzie ścieżką od kodu do znaku przez /ToUnicode i jest tym, co
sprawdza każdy maszynowy konsument. Dokument może zaliczyć pierwsze i całkowicie
nie spełnić drugiego, ponieważ z założenia nie ma niczego wizualnego, co by to
ujawniło.
Druga, subtelniejsza pułapka: założenie, że glif „oczywiście” wie, którym jest znakiem. Nie wie. Glif to kształt z indeksem. Odwzorowanie z powrotem na znak to dodatkowa informacja, którą musi dostarczyć producent. Jeśli producent nigdy jej nie zapisał, żaden czytnik nie odzyska jej wiernie — może jedynie zgadywać.
Granice i ograniczenia
Dział zatytułowany „Granice i ograniczenia”| Edition | Availability |
|---|---|
| Core | NextPDF emituje poprawną CMap /ToUnicode dla osadzanych czcionek, w tym dla przypadków ligatur i czcionek złożonych, dzięki czemu tworzone przez niego dokumenty da się wyszukiwać i kopiować. |
| Pro | Not in this edition |
| Enterprise | Not in this edition |
Odwzorowanie /ToUnicode może nieść tylko informację, którą faktycznie odsłania
czcionka źródłowa. Tam, gdzie glif nie ma dającego się ustalić znaku — czysto
ozdobny znak, symbol z obszaru prywatnego użytku bez przypisania Unicode — żadne
odwzorowanie nie wymyśli znaczenia, którego nigdy tam nie było. NextPDF emituje
prawdziwe odwzorowanie, które potrafi wyprowadzić; nie fabrykuje znaków, by
wypełnić lukę.
Ta strona dotyczy dokumentów, które NextPDF zapisuje. Nie jest to narzędzie do
naprawy dowolnych przychodzących plików PDF, których /ToUnicode jest już
nieobecny lub błędny; odzyskiwanie tekstu z takich plików to osobny, heurystyczny
problem. A wierna ekstrakcja jest konieczna dla dostępności, ale nie jest jej
całością — kolejność odczytu, znaczniki i tekst alternatywny są omówione w
Co czyni PDF dostępnym.
Mini-FAQ
Dział zatytułowany „Mini-FAQ”Dlaczego ten sam plik PDF kopiuje się dobrze w jednym czytniku, a źle w innym?
Różne czytniki różnie radzą sobie, gdy brakuje /ToUnicode. Niektóre zgadują na
podstawie wbudowanego kodowania czcionki i mają szczęście przy zwykłym tekście
łacińskim; inne nie. Poprawny /ToUnicode usuwa tę loterię — każdy zgodny
czytnik dostaje te same znaki.
Czy to to samo, co nieosadzona czcionka?
Nie. Osadzanie dotyczy wyglądu — tego, czy glif maluje się bez zainstalowanej
czcionki. /ToUnicode dotyczy znaczenia — tego, czy kod odwzorowuje się z
powrotem na znak. Czcionka może być idealnie osadzona, a mimo to nie mieć
użytecznego /ToUnicode, co jest awarią typu „niewyszukiwalne, ale ładne”.
Czy ekstrakcja kiedykolwiek potrzebuje więcej niż jednego znaku na kod?
Tak — przypadek ligatury jest dokładnie taki: jeden kod odwzorowuje się na dwa
znaki. Wpis /ToUnicode może odwzorować pojedynczy kod na krótką sekwencję, co
jest sposobem, w jaki ligatury oraz niektóre formy złożone wracają jako litery
składowe.
Powiązane dokumenty
Dział zatytułowany „Powiązane dokumenty”- Czcionki: ta trudna część — towarzysząca część po stronie wyglądu: osadzanie, tworzenie podzbiorów i sposób budowy kodowania. Ta strona to strona znaczenia tej samej monety.
- Co czyni PDF dostępnym — wierny tekst to jeden składnik; kolejność odczytu, znaczniki i tekst alternatywny to reszta.
- Czym właściwie jest PDF — model
obiektowy, w którym żyją czcionki, kodowania i strumienie
/ToUnicode.
Słowniczek
Dział zatytułowany „Słowniczek”- Glif — kształt wizualny w czcionce (obrys). To, co PDF faktycznie maluje. Glif ma indeks, ale nie ma wewnętrznego znaczenia znakowego.
- Znak — jednostka języka pisanego, identyfikowana przez punkt kodowy Unicode. To, co masz na myśli, i to, co ekstrakcja próbuje odzyskać.
- Kod — wartość numeryczna w strumieniu zawartości, która wybiera glif z bieżącej czcionki. Nie jest to znak Unicode; ma znaczenie tylko względem czcionki.
- CID — identyfikator znaku używany przez czcionkę złożoną do zaadresowania glifu w dużym zestawie; krok pośredni między kodem a glifem.
- Czcionka złożona (Type 0) — czcionka, która odczytuje wielobajtowe kody przez CMap, aby dotrzeć do CID-ów i glifów, używana, gdy jedna czcionka musi zaadresować tysiące glifów.
/ToUnicode— strumień CMap, który odwzorowuje kody używane przez dokument z powrotem na wartości Unicode; mechanizm, który sprawia, że tekst PDF da się wyszukiwać, kopiować i jest dostępny.- Ligatura — pojedynczy glif, który rysuje dwie lub więcej liter jako jeden
kształt (na przykład
fi); jego wpis/ToUnicoderozkłada go z powrotem na jego znaki.