AlivePDF. Создание pdf-документов из flash

September 21, 2009Comments Off on AlivePDF. Создание pdf-документов из flash

И Flash и PDF - давно известные всем технологии с четко очерченным набором возможностей и сферой применения. Может показаться, что эти сферы настолько различны, что ничего общего у flash и pdf быть не может. Однако это не так. И как всегда случается на стыке двух технологий, “смесь” pdf и flash не только возможна, но и очень интересна.

Чтобы сразу закрыть вопрос о дальнейшем содержимом статьи, я хочу сказать, о чем я не собираюсь рассказывать. Во-первых, я не будут рассказывать о методиках внедрения внутрь pdf-документов flash-роликов. Это возможно, и при использовании соответствующего программного обеспечения (adobe acrobat, но только не reader) сводится к нажатию всего одной кнопки “Добавить внутрь pdf-странички flash ролик”. Более того, если вы рассматриваете задачу генерации pdf-документов на лету, т.е. в виде какого-то серверного или desktop-приложения, то это также возможно и автор имел опыт работы с java и itext. Также я не буду рассказывать о том, как можно конвертировать pdf-файлы в swf-файлы и обратно. Опять таки все сводится к наличию большого количества бесплатных и платных инструментов. Здесь я могут только порекомендовать познакомиться с swftools (домашний сайт проекта http://www.swftools.org/). Swftools – это набор бесплатных утилит для различных операционных систем, которые позволяют преобразовывать pdf-файлы и картинки (png, jpg, gif) в swf-ролики. В том случае, если вам захочется выполнить преобразование в swf произвольного документа (например, файла msword), то рекомендую обратиться к adobe flashpaper (http://www.adobe.com/products/flashpaper/). Так после установки flashpaper у вас на компьютере появится новый виртуальный принтер, на который можно распечатать любой документ. После завершения “печати” откроется диалоговое окно flashpaper и предложит вам сохранить сформированный файл либо как pdf-документ, либо как swf-ролик. Во втором случае, приятно, что вы получаете в свое распоряжение не “голый” flash-ролик, но небольшое интерактивное приложение с кнопками навигации по swf-документу, функцией масштабирования изображения и т.д. В том случае, если вы хотите сделать pdf или любой другой документ доступным для просмотра любым пользователем internet, то я рекомендую попробовать такой online сервис как http://www.scribd.com/. После регистрации вам будет предоставлена форма загрузки на сервер файлов (поддерживается pdf, файлы ms office и open office). После чего загруженный вами файл становится доступным для просмотра любому пользователю (если вы только не пометили файл как “частный”). Ваш документ в форме swf-ролика может быть просмотрен любым пользователем, даже если у него нет на компьютере pdf reader или ms office. Также как и в случае с flashpaper будут доступны кнопки навигации по документу, функция “поделиться файлом с друзьями” и т.д. Одним словом, scripd – замечательный сервис для хранения документов. Еще одна из интересных задач связанных с конвертирование документов в flash-формат – это создание презентаций. Конечно, сам flash и был предназначен изначально для создания красочных, интерактивных демонстраций, анимационных роликов. Но работа эта требует определенной квалификации и гораздо лучше, если подготовка презентации будет выполнена в ms powerpoint, с последующим преобразованием файла презентации в flash-ролик, который можно внедрить на html-страничку. Подобный сценарий может быть выполнен с помощью упоминавшегося ранее онлайн-сервиса http://www.scribd.com/, либо “настольного” приложения http://www.ispring.ru/. Итак все же, о какой сфере интеграции flash и pdf я хочу рассказать, если это не задачи конвертирования форматов или внедрения в pdf-файлы flash-роликов? Тема сегодняшней статьи это то, как flash-ролик может создать “с нуля” (сгенерировать) pdf-файл с помощью библиотеки AlivePDF. Но сначала пару слов, зачем все это нужно.

Всякий раз, когда возникает разговор о необходимости подготовки документов для печати с использованием сложного макетирования и форматирования материалов, на первые роли выходит pdf. И не важно то, на каком устройстве (desktop или мобильные компьютеры) или на какой операционной системе вы откроете подготовленный файл pdf. Вы всегда можете быть уверены в том, что он будет выглядеть именно так, как планировал автор. Что касается flash, то здесь большинство “молодых” интернет пользователей считает, что сфера flash – это все возможные баннеры и анимация. В действительности flash следует рассматривать шире и, прежде всего, как платформу, в рамках которой могут выполняться приложения. Эта платформа (flash player) легко внедряется как в веб-странички, так и доступна для запуска desktop-приложений. Фактически, если у вас есть какая-то хорошая идея по разработке и продвижению приложения, то вы можете “доставить” конечный продукт наибольшему количеству пользователей, во-первых, в форме online-сервиса. Т.е. пользователь подключается к internet, открывает в браузере ваш сайт и работает либо с flash-приложением, либо с javascript-приложением. Однако не все приложения имеют смысл делать как online. И причина в этом не только в затратах на подключение к internet, но, прежде всего, в том, что веб-приложения по своей природе ограничены в доступе к средствам операционной системы. Нет доступа к панели задач, system tray, нет прямого доступа к файловой системе и т.д. Именно по этой причине появился такой продукт как adobe air. Важным моментом является, то что написанные “под” air desktop проекты могут быть с небольшими затратами перенесены внутрь веб-страниц и обратно. Таким образом, разработка приложений на flash/flex/air очень выгодна возможностью одновременной разработки как online-версии приложения, так и ее более “продвинутой” настольной версии, активно использующей все плюсы интеграции с операционной системой. Совсем недавно мне пришлось разрабатывать “толстый” клиент для корпоративного приложения. Что делало это приложение не столь важно – главное то, что результатом его работы были, в том числе, и все возможные отчеты: отчеты о финансах, о товарах, о затраченных ресурсах и т.д. Когда возник вопрос о том, в каком формате подготавливать документы отчетов перед печатью или рассылкой их по почте, то не было никаких сомнений, что это должен быть pdf. Даже такие “дизайнерские” приложения как онлайн-галлерея изображений или конструктор интерьеров помещений, нуждается в возможности экспорта результатов работы в pdf-файл для последующей печати или отправке по email.

Технически, есть огромное количество библиотек позволяющих генерировать “на лету” pdf-документы; и доступны эти библиотеки для различных языков: java, .net, php. Например, разрабатывая даже flash-интерфейс для online-приложения, вы можете делегировать ответственность по созданию pdf-файла с отчетом к серверному скрипту на php или java. Но если вспомнить, что изначально я поставил цель создания двух версий приложения, т.е. online и настольной версии, работающей без подключения к internet и максимально общего у них кода. То нам потребуется такой инструмент, который позволит создавать pdf-документы без помощи расположенных на сервер утилит – т.е. библиотека создания pdf-файла должна быть написана на actionscript и выполняться внутри flashplayer. Именно об этом я и хочу рассказать на примере работы с библиотекой AlivePDF.

Начнем с того, что загрузим с сайта http://www.alivepdf.org/ архив с библиотекой. После того как мы распакуем архив, то получим в свое распоряжение не только скомпилированный файл библиотеки AlivePDF.swc, но и каталог с исходными кодами. Также у нас в распоряжении будет каталог с документацией по всем классам библиотеки и, что самое приятное, два небольших примера для adobe flash cs3 и для adobe air. Никаких отличий между этими двумя примерами нет, за исключением нюанса связанного с сохранением сгенерированного pdf-документа. Дело в том, что air-приложения имеют прямой доступ к файловой системе компьютера и могут сохранить pdf-файл хоть на ваш рабочий стол. А вот “обычные” flash-ролики в доступе к файловой системе ограничены. Поэтому для онлайн-приложений приходится использовать трюк, когда сгенерированный pdf-файл отправляется на веб-сервер лишь только за тем, чтобы браузер клиента мог получить ссылку на этот pdf-файл и загрузить его обратно на компьютер клиента. Подробнее о методике сохранения pdf-файла будет написано ближе к концу статьи.

Весь последующий код я специально писал в среде adobe flash cs3, как более знакомой для массового пользователя. Но вы, конечно, можете пользоваться любой средой разработки, хоть flashdevelop, хоть adobe flex builder или intellij idea (начиная с восьмой версии idea поддерживает разработку flex и air-приложений). Для Adobe Flash CS3 заходим в меню “Edit -> Preferences -> закладка ActionScript -> кнопка ActionScript 3 Settings”. В появившемся диалоговом окне выбираем путь к каталогу, где находятся исходники AlivePDF (в исходном архиве это Core/SWC – Sources). После чего вы создаете новый проект с типом ActionScript3 и импортируете основные пакеты библиотеки alivepdf:
  1. import org.alivepdf.display.*;
  2. import org.alivepdf.fonts.*;
  3. import org.alivepdf.images.*;
  4. import org.alivepdf.layout.*;
  5. import org.alivepdf.pages.*;
  6. import org.alivepdf.pdf.*;
  7. import org.alivepdf.saving.*;
Теперь начинаем писать, собственно, код создающий pdf-документ. Начнем с того, что создадим “главный” класс PDF, указав при этом его конструктору информацию об ориентации страниц документа, их размере (A3, A4, A5, LETTER, LEGAL, TABLOID) и используемых единицах измерения.
  1. var myPDF:PDF = new PDF(Orientation.PORTRAIT, Unit.MM, Size.A4)
Создав заготовку документа, рекомендуется указать для него такие атрибуты как заголовок, сведения об авторе и набор ключевых слов. В последующем вы можете увидеть указанные вами сведения, если откроете pdf-документ в acrobat reader-е и зайдете в меню “Файл -> Свойства” (см. рис. 1).


  1. myPDF.setTitle("My Simple PDF document");
  2. myPDF.setAuthor("black zorro");
  3. myPDF.setSubject("pdf investigation")
  4. myPDF.setKeywords("Perspectives, High technologies");
Еще из функций, которые наверняка пригодятся, можно упомянуть метод установки полей страницы (лево, верх, право, низ):
  1. myPDF.setMargins(50, 10, 50, 10);
Следующий шаг - это настройка того, с какими настройками по-умолчанию откроется, используемый нами просмотрщик pdf, т.е. тот же adobe acrobat reader. Первым параметром методу setDisplayMode идет указание стратегии масштабирования страниц. Помимо показанного в примере FULL_WIDTH (подогнать ширину страницы под размер экрана), есть еще и FULL_PAGE (отображать всю страницу целиком). Мы можем указать сами коэффициент масштабирования в режиме REAL или даже уточнить то, какая область документа должна быть изначально открыта (RECTANGLE). Второй параметр метода setDisplayMode позволяет указать то, как страницы будут упорядочены в ходе просмотра. Т.е. будем ли мы видеть на экране только одну страницу (SINGLE_PAGE) или несколько и в каком порядке (TWO_PAGE_RIGHT и TWO_PAGE_LEFT). Параметров, управляющих просмотром документа довольно много и лучший способ разобраться с ними – побольше экспериментировать:
  1. // масштабируем по ширине страницы и размещаем содержимое в две колонки с первой страницей справа
  2. myPDF.setDisplayMode(Display.FULL_WIDTH, Layout.TWO_COLUMN_RIGHT);
  3. // видим на экране выделенную область первой страницы
  4. myPDF.setDisplayMode(Display.RECTANGLE, Layout. SINGLE_PAGE, PageMode.USE_OUTLINES, 1, new Rectangle(0,0, 100, 100));
  5. // масштаб в 200%
  6. myPDF.setDisplayMode(Display.REAL, Layout.TWO_PAGE_LEFT, PageMode.USE_OUTLINES, 2);
После того как был создан pdf документ и установлен режим просмотра, самое время заняться информационным наполнением файла, т.е. создать страницы. Создавая страницу, мы можем указать ее размеры и ориентацию, в том случае если они отличается от настроек по-умолчанию. Если не указать никакого параметра при вызове метода addPage, то будет добавлена именно такая страница с настройками по-умолчанию:
  1. var firstPage:Page = new Page(Orientation.PORTRAIT, Unit.MM, Size.A4);
  2. myPDF.addPage(firstPage);
Получив в свое распоряжение страницу, мы начинаем наполнять ее содержимым. Даже самое простое – вывод текста – можно сделать с помощью различных методов и каждый из них имеет свои нюансы. Перед выводом текста нужно установить параметры шрифта с помощью метода setFont, а с помощью метода textStyle задается цвет символов:
  1. myPDF.setFont(FontFamily.HELVETICA, Style.BOLD_ITALIC, 18);
  2. myPDF.textStyle ( new RGBColor ( 0xff0000 ) );
Следующий шаг - вызов метода writeText. Ее параметры это высота линии, сам текст и опциональная гиперссылка. В том случае, если третий параметр указан, то pdf-файл будет содержать не просто кусочек текста, но и гиперссылку на какой-либо сайт:
  1. myPDF.writeText(50, "Click here to visit my site 1", "http://site.site");
Последующие вызовы метода writeText будут продолжать выводить текст на той же строке, пока она не закончится (либо вы явно прервете строку, выведя символ “\n”). Каждая из последующих строк будет начинаться с отступом относительно предыдущей в 50 мм. Так что, если указать недостаточную высоту линий, то выводимый текст сольется. Выводя текст можно не беспокоиться о том, что высоты страницы не хватит для него: alivepdf автоматически начнет новую страницу, как только это потребуется. Еще один способ вывода текста – это метод addMultiCell. Он автоматически побеспокоится о переносах текста, если он не будет вмещаться в указанный вами прямоугольник шириной в 100 мм. Для того, чтобы строки не сливались я указал каждую новую строку начинать отступом от предыдущей в 10 мм. Четвертый параметр включает отображение вокруг области текста прямоугольника границы. И последний параметр задает выравнивание текста по правому краю “R”.
  1. myPDF.addMultiCell(100, 10, "Некоторый очень длинный текст", 1, "R");
В том случае, если вы хотите получить абсолютный контроль за позиционированием выводимого текста, то можно использовать метод setXY с указанием координат, перед тем как вы начнете печатать текст:
  1. myPDF.setXY(10, 10);
  2. myPDF.writeText(10, "Absolutely Positioned Text");
Большой пласт функциональности alivepdf связан с рисованием 2d-примитивов. В следующем примере я покажу то, как можно нарисовать круг и прямоугольник (см. рис. 2).



Сначала я вызвал метод lineStyle, который настраивает характеристики всех рисуемых в дальнейшем линий (цвет и толщина линий). Затем я включаю режим заливки фона рисуемых фигур методом beginFill (цвет фона). В арсенале AlivePdf есть как “высокоуровневые” функции, рисующие сразу всю фигуру целиком (в примере круг), так и рисующие фигуру из отдельных линий. Во втором случае я последовательно задаю координаты всех вершин полигона и завершаю рисование (функция end).
  1. myPDF.lineStyle(new RGBColor(0x0000ff ), 2);
  2. myPDF.beginFill(new RGBColor(0xff0000));
  3. // рисуем круг
  4. myPDF.drawCircle(100, 100, 50)
  5. // рисуем прямоугольник
  6. myPDF.moveTo ( 50, 50 );
  7. myPDF.lineTo ( 100, 50 );
  8. myPDF.lineTo ( 100, 100 );
  9. myPDF.lineTo ( 50, 100 );
  10. myPDF.end()
  11. myPDF.endFill();
Более удобный способ рисования фигур-полигонов – это метод drawPolygone. Единственным параметром для которого является массив с координатами вершин рисуемой фигуры:
  1. myPDF.drawPolygone ([100, 100, 120, 100, 120, 120]);
Более полезной, чем “ручное” рисование фигур на pdf-листе, является функция внедрения внутрь pdf-документа подготовленных заранее картинок. Сначала я покажу подход, когда внутрь swf файла внедряется двоичное представление картинки, а затем она рисуется на pdf-странице. Здесь важно помнить, что внедренные картинки в отличие от нарисованных вручную фигур представляют собой растровые картинки. А, значит, увеличив масштаб просмотра до больших величин, у вас будет возможность “познакомиться” с отдельными пикселями, составляющими картинку. Для следующего примера я сначала добавил в исходный код приложения директиву “внедрить” в swf-файл содержимое файла “foxmoving.jpg”.
  1. [Embed( source="/assets/foxmoving.jpg", mimeType="application/octet-stream" )]
  2. private var foxImage:Class;
А теперь можно попросить alivepdf нарисовать эту картинку:
  1. myPDF.addPage();
  2. myPDF.addImageStream(new foxImage() as ByteArray,100, 100, 500, 500);
Первый параметр функции addImageStream очевиден – ссылка на картинку. Затем идут координаты места, где нужно нарисовать картинку и размер прямоугольной области для этого. Также вы можете попросить alivepdf масштабировать изображение или превратить его в http-ссылку. Что касается поддерживаемых форматов изображений, то это только png и jpg. Есть еще одна методика рисования на pdf-листе, которая предполагает, что изображение будет скопировано с некоего flash-клипа или класса производного от flash.display.DisplayObject (см. рис. 3).



К примеру, flash-приложение, представляющее собой конструктор дизайна интерьера, может скопировать нарисованный на себе же проект квартиры в pdf-файл:
  1. myPDF.addImage(this, 0, 0, 0, 0, ImageFormat.PNG);
Параметры метода addImage сходны с теми, которые были у предыдущего метода рисования – addImageStream: ссылка на DisplayObject, координаты, где будет нарисована картинка, затем размер прямоугольной области и формат картинки (png или jpg).

Последнее действие, которое будет выполнено после завершения подготовки pdf-файла – так это его сохранение. Во-первых, файл можно отправить для сохранения на сервер:
  1. myPDF.save(Method.REMOTE, "http://my-site.com/script.php", "inline", "AlivePdfDemo.pdf");
Здесь двоичное представление pdf-файла будет отправлено по адресу "http://my-site.com/script.php". Также серверному скрипту будет передана переменная method, равная слову “inline”. Глубокого смысла в этой переменной нет, разве что вы воспользуетесь как основой, идущими в составе AlivePDF примерами скриптов create.cs, create.java или create.php. Вся работа этих скриптов сводится к отправке обратно полученного pdf-файла. В общем случае, ваш серверный скрипт может делать что-либо иное, например, сохранить файл на сервере для последующего просмотра или отправить pdf-файл на email.

В случае, если вы создаете air приложение, имеющее прямой доступ к файловой системе, то можно сохранить pdf-документ сразу на жесткий диск, например, так:
  1. var f:FileStream = new FileStream();
  2. var file: File = File.desktopDirectory.resolvePath("AliveDemo.pdf");
  3. f.open(file, FileMode.WRITE);
  4. var bytes:ByteArray = myPDF.save(Method.LOCAL);
  5. f.writeBytes(bytes);
  6. f.close();
Я специально останавливаюсь на только одной статье, рассказывающей о AlivePDF. Т.к. возможностей по форматированию содержимого pdf-документа очень-очень много, а не хочу ставить перед собой задачу написания малополезного супер-справочника. Достаточно того, чтобы вы понимали цель и сферу применения alivepdf, а в деталях использования, конкретных параметрах для конкретных функций, можно разобраться, просто, экспериментируя.

Categories: Flash & Flex