Большой архив статей, книг, документации по программированию, вебдизайну, компьютерной графике, сетям, операционным системам и многому другому
 
<Добавить в Избранное>    <Сделать стартовой>    <Реклама на сайте>    <Контакты>
  Главная Документация Программы Обои   Экспорт RSS E-Books
 
 

   Программирование -> Delphi / Pascal -> Очерк по поводу создания PDF-файлов


Очерк по поводу создания PDF-файлов

В последнее время на просторах интернета обнаружилось очень много PDF converter'ов, reader'ов и write'ов. И подавляющее большинство из них предлагается за деньги. Сама программа от 10$ до 300$. А уж исходный код за гораздо большие деньги цена начинается от 200$ а в одном месте (заинтересовавшись этим полазил по инету) аж за 900 евро.

Данная проблемма меня заинтересовала в плане программирования и вот результаты довожу до вашего сведения. (Данные результаты получены мною при изучении внутренностей PDF файла, когда открываешь его в total commander через F3)

Обычный PDF файл состоит из четырех частей

<PDF file> :=	<header>
<body>
<cross-reference table>
<trailer>

Что такое такое <header>? Это обычное упоминание о версии PDF specification. Которое присутствует в первой строке PDF файла. Например "%PDF-1.3" В седьмой версии акробата которая вышла где то в начале лета этого года, этот номер "%PDF-1.7", но это не версия продукта, это версия именно спецификации. Второй строкой PDF идет небольшая аброкадабра (видимо предназначена для дальнейшего использования) " %вгПУ"

Все с первой частью PDF разобрались.

Что из себя представляет вторая часть которая называется <body>?

Ответ очень простой: это последовательность объектов, описание которых как и хедера представлены в текстовом виде.

Каждый объект это текстовой фрагмент с порядковым номером в имени например "4 0 obj"

  • 4 это порядковый номер объекта
  • 0 это номер (ре)генерации файла то есть когда файл обновляется (редактируется ) то данный номер увеличивается
  • obj это кодовое слово означающее что в теле документа нам встретился объект

Все объекты делятся на косвенные и прямые. Все косвенные, и их большинство, после слова obj имеют в своем теле делиметер "<<", означающее начало данных объекта. И в конце данных закрывающий делиметер ">>" и кодовое слово endobj

Прямые объекты не должны иметь в своем теле открывающих и закрывающих делиметеров "<<", ">>" Все косвенные объекты доступны через cross-reference table. В ней представлены ссылки в виде смещения от начала файла до начала объекта (Данные (строки) в объекте разделяются #13#10 либо #13)

Тип "самого главного" объекта в теле PDF файла носит гордое имя "/Catalog"

4 0 obj 
<<  
/Type /Catalog  
/Pages 2 0 R  
/OpenAction [ 5 0 R /XYZ null 364 1 ]  
/PageMode /UseNone  
>> 
endobj

На самом деле в теле минимального PDF файла типа "Hello world" должно быть 3 "главных" объекта. Давайте я их перечислю по типам:

  • "/Catalog" содержит в себе ссылку : на дерево страниц (/Pages)
  • "/Pages" содержит в себе ссылку на группу страниц документа
    (Например
    2 0 obj  
    <<  
    /Type /Pages  
    /Kids [ 3 0 R ]  
    /Count 1  
    >>  
    endobj
    )
  • "/Page" содержит в себе ссылку на объекты относящиеся к конкретной странице.
    (Например
    3 0 obj 
    <<  
    /Type /Page  
    /Parent 2 0 R  
    /MediaBox [ 0 0 612 792 ]  
    /CropBox [ 0 0 612 792 ]  
    /Contents 4 0 R  
    /Resources << /Font 20 0 R /ProcSet [ /PDF /Text ] >>  
    /Rotate 0  
    >>  
    )

И несколько "второстепенных"

Разберем объект страница:

  • /Rotate поле показывающее на сколько градусов изображение страницы должно быть повернуто при отображение в программе
  • /MediaBox и /CropBox поля описывающие размер страницы
  • /Parent ссылка на родительский объект "/Pages"
  • /Resources это поле описывает какой фонт должен быть использован при отображении страницы (фонт это отдельный объект) и установку ProcSet эта установка показывает какое содержимое потока данных данной страницы (тоже может быть определен как объект, а не как поле)
  • /Contents Самое интересное поле в объекте "страница", дает ссылку на объект содержимого данной страницы, причем : если это поле отсутствует в объекте "страница" значит страница пустая

Содержимое страницы:

Объект "stream"

4 0 obj << /Length 305 >>  stream
BT
/F12 9 Tf
10 782 TD
0 -12.5 TD
(                                                   Max Fokin) Tj
0 -12.5 TD
(          mnb) Tj
0 -12.5 TD
() Tj
0 -12.5 TD
(Max               Privet) Tj
0 -12.5 TD
( 1) Tj
0 -12.5 TD
(1) Tj
0 -12.5 TD
(2) Tj
0 -12.5 TD
(3) Tj
0 -12.5 TD
(45) Tj
ET
endstream endobj

/Length 305 - это поле показыввающее сколько байт от слова stream до слова endstream

Самый простой вариант — это некодированный и несжатый поток данных в объекте stream. Он ограничивается операторами BT и ET

BT Begins a Text Object  - характеризует начало текста
ET Ends a Text Object.   - характеризует конец текста

/F12 9 Tf -

  • /F12 это кодовое имя объекта который характеризует фонт используемый на данной странице
  • 9 это размер фонта
  • Tf это оператор который характеризует что данная строка в объекте steam есть установка фонта и размера

10 782 TD - это цифры откуда начинается данная строка (отсчет производиться от левого верхнего угла)

Tj - это оператор перевода на новую строку

Ну а в круглых скобках наш текст

Кодированный поток я сдесь не объясняю. Он основан на алгоритмах RC4, RC5, MD5.

Что такое объект Font

12 0 obj 
<<  
/Type /Font  
/Subtype /Type1  
/Name /F7  
/BaseFont /Courier-Oblique  
/Encoding /WinAnsiEncoding  
>> 
  • /Type /Font Естественно название типа
  • /Subtype /Type1 название подтипа
  • /Name /F7 F7 это кодовое имя

PDF поддерживает несколько видов фонтов. Они перечисленны ниже

  • Type 1, including subsets and Multiple Master "snapshots"
  • Type 3
  • TrueType, including subsets
  • Type 0

Честно говоря, я не разбирался с Type 3, TrueType, including subsets, Type 0 ничего по ним сказать не могу.
А Type 1 — это следующие фонты

Courier
Courier-Bold
Courier-BoldOblique
Courier-Oblique
Helvetica
Helvetica-Bold
Helvetica-BoldOblique
Helvetica-Oblique
Times-Roman
Times-Bold
Times-Italic
Times-BoldItalic
Symbol
ZapfDingbats
20 0 obj 
<<  
/F1 6 0 R  
/F2 7 0 R  
/F3 8 0 R  
/F4 9 0 R  
/F5 10 0 R  
/F6 11 0 R  
/F7 12 0 R  
/F8 13 0 R  
/F9 14 0 R  
/F10 15 0 R  
/F11 16 0 R  
/F12 17 0 R  
/F13 18 0 R  
/F14 19 0 R  
>>  
endobj

Это объект с названиями кодовых имен для фонтов первого типа. По этому кодовому имени можно легко получить сам объект фонт.

6 0 obj 
<<  
/Type /Font  
/Subtype /Type1  
/Name /F1  
/BaseFont /Helvetica  
/Encoding /WinAnsiEncoding  
>>  

ВСЕ: то есть минимальное <Body> Состоит из следующих объектов: "catalog" , "pages", "page", "Resources" (опиционально может присутствовать, как поле в объекте страница), нетипизированный объект "stream", группа объектов "font"

Что такое <cross-reference table>?
На самом деле это обычная текстовая таблица, она начинается со слова xref и своем теле имеет ссылки на все косвенные объекты в документе. Вот пример

xref 
0 27  
0000000021 65535 f
0000000016 00000 n
0000000105 00000 n
0000000169 00000 n
0000000356 00000 n
0000000713 00000 n
0000000892 00000 n
0000001006 00000 n
0000001125 00000 n
0000001247 00000 n
0000001373 00000 n
0000001486 00000 n
0000001604 00000 n
0000001725 00000 n
0000001850 00000 n
0000001967 00000 n
0000002084 00000 n
0000002203 00000 n
0000002326 00000 n
0000002439 00000 n
0000002558 00000 n
0000000024 00001 f
0000002751 00000 n
0000002831 00000 n
0000000000 00001 f
0000002915 00000 n
0000002955 00000 n
0 27 Эти цифры обозначают следующее :
  • 0 - первый object number в таблице
  • 27 - количество элементов таблицы

Первый элемент таблицы всегда иммет вид "XXXXXXXXXX 65535 f" где X это цифра, а 65535 это значение по умолчанию для первого элемента в таблице. Символ "f" обозначает "free", то есть объект не используется Ссылки на объекты, которые используются, в конце имеют символ "n"

Разберем элемент данной таблицы.

  • Первые 10 цифр — это смещение от начала файла до начала объекта.
  • 0000000016 означает что через 16 байт от начала файла Вас встретит первое упоминание об объекте то есть, например, 4 0 obj

Вторые пять цифр — это номер генерации файла. Если файл только что создан, то они всегда нули. Если файл модифицируется, то это число увеличивается на единицу. То есть, 0000000024 00001 f

Канонический, только что созданный PDF файл, имеет только одну таблицу. Но, если файл редактируется, то таких таблиц может быть очень много.

Взаимосвязь таблиц осуществляется при помощи последнего элемента <trailer> и кодового слова startxref

Канонический, только что созданный PDF файл, имеет только одну таблицу, после таблицы идет элемент trailer

А после трайлера идет кодовое слово startxref, указывающее на смещение от начала файла до начала таблицы, вот пример.

trailer 
<< 
/Size 3 
>> 
startxref 
173 
%%EOF

Это значит, что через 173 байта от начала документа, будет присутствовать кодовое слово xref. Но, если файл был отредактирован, то последний в файле трайлер будет иметь вид:

xref 
0 3  
0000000000 65535 f
0000003609 00000 n
0000003832 00000 n
trailer 
<< 
/Size 3 
/ID[<7a15ab3ed3999575ff2f3034104a82c1><7a15ab3ed3999575ff2f3034104a82c1>] 
>> 
startxref 
173 
%%EOF

Но, если мы обратимся к таблице, куда указывает ссылка startxref 173, то мы найдем следующую таблицу, а за ней трайлер, который будет иметь поле /Prev 3896

3 16  
0000000016 00000 n
0000000664 00000 n
0000000936 00000 n
0000001106 00000 n
0000001133 00000 n
0000001250 00000 n
0000001395 00000 n
0000001811 00000 n
0000001992 00000 n
0000002180 00000 n
0000002360 00000 n
0000002760 00000 n
0000003438 00000 n
0000003516 00000 n
0000000776 00000 n
0000000916 00000 n
trailer 
<< 
/Size 19 
/Info 1 0 R  
/Root 4 0 R  
/Prev 3896  
/ID[<7a15ab3ed3999575ff2f3034104a82c1><7a15ab3ed3999575ff2f3034104a82c1>] 
>> 
startxref 
567
%%EOF

Данное поле /Prev 3896 указывает нам на предыдущую таблицу, а ссылка startxref 567 указывает на следующую таблицу и так практически до бесконечности, пока в очередном поле startxref мы не увидим 0. Это значит, мы прочитали все таблицы.

В данном очерке, конечно, не хватает исходного кода. Вот и он: представлены два модуля основной "PDFDocument" и вспомогательный "PDFBaseFonts"

Исходный код модулей PDFDocument.pas и PDFBaseFonts.pas (.zip, 16 K, обновление от 9/23/2005)

Автор: Максим Фокин
Источник: www.delphikingdom.com

Ссылки по теме
Алгоритмы Сортировки. Часть 1
Введение в Delphi 8
Работа с реестром в Delphi
Delphi и ресурсы компьютера
Советы начинающим программировать на Delphi
Структуры и базы данных, методы сортировки
 

Компьютерная документация от А до Я - Главная

 

 
Интересное в сети
 
10 новых программ
CodeLobster PHP Edition 3.7.2
WinToFlash 0.7.0008
Free Video to Flash Converter 4.7.24
Total Commander v7.55
aTunes 2.0.1
Process Explorer v12.04
Backup42 v3.0
Predator 2.0.1
FastStone Image Viewer 4.1
Process Lasso 3.70.4
FastStone Image Viewer 4.0
Xion Audio Player 1.0.125
Notepad GNU v.2.2.8.7.7
K-Lite Codec Pack 5.3.0 Full


Наши сервисы
Рассылка новостей. Подпишитесь на рассылку сейчас и вы всегда будете в курсе последних событий в мире информационных технологий.
Новостные информеры. Поставьте наши информеры к себе и у вас на сайте появится дополнительный постоянно обновляемый раздел.
Добавление статей. Если вы являетесь автором статьи или обзора на тему ИТ присылайте материал нам, мы с удовольствием опубликуем его у себя на сайте.
Реклама на сайте. Размещая рекламу у нас, вы получите новых посетителей, которые могут стать вашими клиентами.
 
Это интересно
 

Copyright © CompDoc.Ru
При цитировании и перепечатке ссылка на www.compdoc.ru обязательна. Карта сайта.