? Це звичайне згадка про версію PDF specification.
Яке присутній у першому рядку PDF файлу. Наприклад "% PDF-1.3" У
сьомої версії акробата яка вийшла де то на початку літа цього року, цей
номер "% PDF-1.7", але це не версія продукту, це версія саме
специфікації. Другий рядок PDF йде невелика аброкадабра (мабуть
призначена для подальшого використання) "% ВДПУ" p>
Всі
з першою частиною PDF розібралися. p>
Що
із себе представляє другу частину яка називається
? p>
Відповідь
дуже простий: це послідовність об'єктів, опис яких як і хедера
представлені в текстовому вигляді. p>
Кожен
об'єкт це текстовий фрагмент з порядковим номером в імені наприклад "4 0
obj " p>
4
це порядковий номер об'єкта p>
0
це номер (ре) створення файлу тобто коли файл оновлюється (редагується)
то цей номер збільшується p>
obj
це кодове слово означає що в тілі документа нам зустрівся об'єкт p>
Всі
об'єкти діляться на непрямі і прямі. Усі непрямі, і їх більшість, після
слова obj мають у своєму тілі деліметер "<<", що означає початок
даних об'єкта. І в кінці даних закриває деліметер ">>" і
кодове слово endobj p>
Прямі
об'єкти не повинні мати на своєму тілі які відкривають і закривають деліметеров
"<<", ">>" Все непрямі об'єкти доступні через
cross-reference table. У ній представлені посилання у вигляді зміщення від початку
файлу до початку об'єкта (Дані (рядки) в об'єкті розділяються # 13 # 10 небудь # 13)
p>
Тип
"найголовнішого" об'єкта в тілі PDF файлу носить горде ім'я
"/ Catalog" p>
4 0 obj p>
<< p>
/Type/Catalog p>
/Pages 2 0 R p>
/OpenAction [5 0 R/XYZ null 364 1
] P>
/PageMode
/ UseNone p>
>>
p>
endobj p>
На
насправді в тілі мінімального PDF файлу типу "Hello world" повинне
бути 3 "головних" об'єкта. Давайте я їх перерахую за типами: p>
"/ Catalog"
містить в собі посилання: на дерево сторінок (/ Pages) p>
"/ Pages"
містить в собі посилання на групу сторінок документа p>
(Наприклад p>
2 0 obj p>
<< p>
/Type/Pages p>
/Kids [3 0 R] p>
/Count
1 p>
>>
p>
endobj p>
) p>
"/ Page"
містить в собі посилання на об'єкти що відносяться до конкретної сторінки. p>
(Наприклад p>
3 0 obj p>
<< p>
/Type/Page p>
/Parent 2 0 R p>
/MediaBox [0 0 612 792] p>
/CropBox [0 0 612 792] p>
/Contents 4 0 R p>
/Resources < Font 20 0 R
/ ProcSet [/ PDF/Text]>> p>
/Rotate
0 p>
>>
p>
) p>
І
кілька "другорядних" p>
Розберемо
об'єкт сторінка: p>
/Rotate
поле показує на скільки градусів зображення сторінки повинно бути
повернуто при відображення в програмі p>
/MediaBox
та/CropBox поля описують розмір сторінки p>
/Parent
посилання на батьківський об'єкт "/ Pages" p>
/Resources
це поле описує який фонт повинен бути використаний для відображення сторінки
(фонт це окремий об'єкт) і установку ProcSet ця установка показує яке
вміст потоку даних даної сторінки (теж може бути визначений як об'єкт,
а не як поле) p>
/Contents
Найцікавіше поле в об'єкті "сторінка", дає посилання на об'єкт
вмісту цієї сторінки, причому: якщо це поле відсутнє в об'єкті
"сторінка" означає сторінка порожня p>
Вміст
сторінки: p>
Об'єкт
"stream" p>
4
0 obj < Length 305>> stream p>
BT p>
/F12 9 Tf p>
10 782 TD p>
0 -12.5 TD p>
(Max Fokin) Tj p>
0 -12.5 TD p>
(mnb) Tj p>
0 -12.5 TD p>
() Tj p>
0 -12.5 TD p>
(Max Privet) Tj p>
0 -12.5 TD p>
(1) Tj p>
0 -12.5 TD p>
(1) Tj p>
0 -12.5 TD p>
(2) Tj p>
0 -12.5 TD p>
(3) Tj p>
0 -12.5 TD p>
(45)
Tj p>
ET p>
endstream
endobj p>
/Length
305 - це поле показиввающее скільки байт від слова stream до слова endstream p>
Самий
простий варіант - це некодованих і незжатий потік даних в об'єкті stream.
Він обмежується операторами BT і ET p>
BT
Begins a Text Object - характеризує початок тексту p>
ET
Ends a Text Object. - Характеризує кінець тексту p>
/F12
9 Tf - p>
/F12
це кодове ім'я об'єкта який характеризує фонт що використовується на даній
сторінці p>
9
це розмір фонт p>
Tf
це оператор який характеризує що даний рядок в об'єкті steam є
установка фонт та розміру p>
10
782 TD - це цифри звідки починається даний рядок (відлік здійснюватися від
лівого верхнього кута) p>
Tj
- Це оператор перекладу на новий рядок p>
Ну
а в круглих дужках наш текст p>
Кодований
потік я сдесь не пояснюю. Він заснований на алгоритмах RC4, RC5, MD5. p>
Що
таке об'єкт Font p>
12
0 obj p>
<<
p>
/Type/Font p>
/Subtype/Type1 p>
/Name/F7 p>
/BaseFont/Courier-Oblique p>
/Encoding/WinAnsiEncoding p>
>> p>
/Type
/ Font Природно назва типу p>
/Subtype
/ Type1 назва підтипу p>
/Name
/ F7 F7 це кодове ім'я p>
PDF
підтримує декілька видів Фонтен. Вони перераховані нижче p>
Type 1, including subsets and
Multiple Master "snapshots" p>
Type 3 p>
TrueType, including subsets p>
Type 0 p>
Чесно
кажучи, я не переймався Type 3, TrueType, including subsets, Type 0 нічого по
ним сказати не можу. p>
А
Type 1 - це наступні фонт p>
Courier p>
Courier-Bold p>
Courier-BoldOblique p>
Courier-Oblique p>
Helvetica p>
Helvetica-Bold p>
Helvetica-BoldOblique p>
Helvetica-Oblique p>
Times-Roman p>
Times-Bold p>
Times-Italic p>
Times-BoldItalic p>
Symbol p>
ZapfDingbats p>
20 0 obj p>
<< p>
/F1 6 0 R p>
/F2 7 0 R p>
/F3 8 0 R p>
/F4 9 0 R p>
/F5 10 0 R p>
/F6 11 0 R p>
/F7 12 0 R p>
/F8 13 0 R p>
/F9 14 0 R p>
/F10 15 0 R p>
/F11 16 0 R p>
/F12 17 0 R p>
/F13 18 0 R p>
/F14 19 0 R p>
>> p>
endobj p>
Це
об'єкт з назвами кодових імен для фонт першого типу. З цього кодовому
імені можна легко отримати сам об'єкт фонт. p>
6 0 obj p>
<< p>
/Type/Font p>
/Subtype/Type1 p>
/Name/F1 p>
/BaseFont
/ Helvetica p>
/Encoding
/ WinAnsiEncoding p>
>>
p>
ВСЕ:
тобто мінімальний
складається з наступних об'єктів:
"catalog", "pages", "page", "Resources"
(опіціонально може бути присутнім, як поле в об'єкті сторінка),
нетипізований об'єкт "stream", група об'єктів "font" p>
Що таке ? p>
На
Насправді це звичайна текстова таблиця, вона починається зі слова xref і своє
тілі має посилання на всі непрямі об'єкти в документі. Ось приклад p>
xref
p>
0
27 p>
0000000021
65535 f p>
0000000016
00000 n p>
0000000105
00000 n p>
0000000169
00000 n p>
0000000356
00000 n p>
0000000713
00000 n p>
0000000892
00000 n p>
0000001006
00000 n p>
0000001125 00000 n p>
0000001247 00000 n p>
0000001373 00000 n p>
0000001486 00000 n p>
0000001604 00000 n p>
0000001725 00000 n p>
0000001850 00000 n p>
0000001967 00000 n p>
0000002084 00000 n p>
0000002203 00000 n p>
0000002326 00000 n p>
0000002439
00000 n p>
0000002558
00000 n p>
0000000024
00001 f p>
0000002751
00000 n p>
0000002831
00000 n p>
0000000000
00001 f p>
0000002915
00000 n p>
0000002955
00000 n p>
0
27 Ці цифри позначають наступне: p>
0
- Перша object number в таблиці p>
27
- Кількість елементів таблиці p>
Перший
елемент таблиці завжди іммет вид "XXXXXXXXXX 65535 f" де X це
цифра, а 65535 це значення за замовчуванням для першого елемента в таблиці. Символ
"f" означає "free", тобто об'єкт не використовується
Посилання на об'єкти, які використовуються, в кінці мають символ "n" p>
Розберемо
елемент цієї таблиці. p>
Перші
10 цифр - це зсув від початку файлу до початку об'єкта. p>
0000000016
означає що через 16 байт від початку файлу Вас зустріне перша згадка про
об'єкті тобто, наприклад, 4 0 obj p>
Другі
п'ять цифр - це номер створення файлу. Якщо файл щойно створений, то вони
завжди нулі. Якщо файл модифікується, то це число збільшується на одиницю.
Тобто, 0000000024 00001 f p>
Канонічний,
тільки що створений PDF файл, має тільки одну таблицю. Але, якщо файл
редагується, то таких таблиць може бути дуже багато. p>
Взаємозв'язок
таблиць здійснюється за допомогою останнього елемента і кодового
слова startxref p>
Канонічний,
тільки що створений PDF файл, має тільки одну таблицю, після таблиці йде
елемент trailer p>
А
після Трайлер йде кодове слово startxref, яке вказує на зсув від початку
файлу до початку таблиці, ось приклад. p>
trailer
p>
<<
p>
/Size
3 p>
>>
p>
startxref
p>
173
p>
%% EOF p>
Це
означає, що через 173 байти від початку документа, буде присутній кодове
слово xref. Але, якщо файл був відредагований, то останній у файлі Трайлер
буде мати вигляд: p>
xref p>
0 3 p>
0000000000 65535 f p>
0000003609 00000 n p>
0000003832 00000 n p>
trailer p>
<< p>
/Size 3 p>
/ID [<7a15ab3ed3999575ff2f3034104a82c1> <7a15ab3ed3999575ff2f3034104a82c1>]
p>
>> p>
startxref p>
173 p>
%% EOF p>
Але,
якщо ми звернемося до таблиці, куди вказує посилання startxref 173, то ми знайдемо
наступну таблицю, а за нею Трайлер, який буде мати поле/Prev 3896 p>
3 16 p>
0000000016 00000 n p>
0000000664 00000 n p>
0000000936 00000 n p>
0000001106 00000 n p>
0000001133 00000 n p>
0000001250 00000 n p>
0000001395 00000 n p>
0000001811 00000 n p>
0000001992 00000 n p>
0000002180 00000 n p>
0000002360 00000 n p>
0000002760 00000 n p>
0000003438 00000 n p>
0000003516 00000 n p>
0000000776 00000 n p>
0000000916 00000 n p>
trailer p>
<< p>
/Size 19 p>
/Info 1 0 R p>
/Root 4 0 R p>
/Prev 3896 p>
/ID [<7a15ab3ed3999575ff2f3034104a82c1> <7a15ab3ed3999575ff2f3034104a82c1>]
p>
>>
p>
startxref
p>
567 p>
%% EOF p>
Дане
поле/Prev 3896 вказує нам на попередню таблицю, а посилання startxref 567
вказує на наступну таблицю і так практично до нескінченності, поки в
черговому полі startxref ми не побачимо 0. Це значить, ми прочитали всі таблиці. p>
В
даному нарисі, звичайно, не вистачає вихідного коду. Ось і він: представлені два
модуля основний "PDFDocument" і допоміжний
"PDFBaseFonts" p>
Список літератури h2>
Для
підготовки даної роботи були використані матеріали з сайту http://www.citforum.ru/
p>