Flash & PDF. Путешествие туда и обратно

И 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 или любой другой документ доступным для просмотра любым пользователем Интернета, то я рекомендую попробовать такой 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-файл для последующей печати или отправке по e-mail.

Технически, есть огромное количество библиотек, позволяющих генерировать “на лету” 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:

import org.alivepdf.display.*;
import org.alivepdf.fonts.*;
import org.alivepdf.images.*;
import org.alivepdf.layout.*;
import org.alivepdf.pages.*;
import org.alivepdf.pdf.*;
import org.alivepdf.saving.*;

Теперь начинаем писать, собственно, код, создающий pdf-документ. Начнем с того, что создадим “главный” класс PDF, указав при этом его конструктору информацию об ориентации страниц документа, их размере (A3, A4, A5, LETTER, LEGAL, TABLOID) и используемых единицах измерения.

var myPDF:PDF = new PDF(Orientation.PORTRAIT, Unit.MM, Size.A4)

Создав заготовку документа, рекомендуется указать для него такие атрибуты, как заголовок, сведения об авторе и набор ключевых слов. В последующем вы можете увидеть указанные вами сведения, если откроете pdf-документ в acrobat reader-е и зайдете в меню “Файл -> Свойства” (см. рис. 1).

myPDF.setTitle("My Simple PDF document");
myPDF.setAuthor("black zorro");
myPDF.setSubject("pdf investigation")
myPDF.setKeywords("Perspectives, High technologies");

Еще из функций, которые наверняка пригодятся, можно упомянуть метод установки полей страницы (лево, верх, право, низ):

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). Параметров, управляющих просмотром документа, довольно много и лучший способ разобраться с ними – побольше экспериментировать:

// масштабируем по ширине страницы и размещаем содержимое в две колонки с первой страницей справа
myPDF.setDisplayMode(Display.FULL_WIDTH, Layout.TWO_COLUMN_RIGHT);
// видим на экране выделенную область первой страницы
myPDF.setDisplayMode(Display.RECTANGLE, Layout. SINGLE_PAGE, PageMode.USE_OUTLINES, 1, new Rectangle(0,0, 100, 100));
// масштаб в 200%
myPDF.setDisplayMode(Display.REAL, Layout.TWO_PAGE_LEFT, PageMode.USE_OUTLINES, 2);

После того как был создан pdf-документ и установлен режим просмотра, самое время заняться информационным наполнением файла, т.е. создать страницы. Создавая страницу, мы можем указать ее размеры и ориентацию, в том случае если они отличается от настроек по умолчанию. Если не указать никакого параметра при вызове метода addPage, то будет добавлена именно такая страница с настройками по умолчанию:

var firstPage:Page = new Page(Orientation.PORTRAIT, Unit.MM, Size.A4);
myPDF.addPage(firstPage);

Получив в свое распоряжение страницу, мы начинаем наполнять ее содержимым. Даже самое простое – вывод текста – можно сделать с помощью различных методов, и каждый из них имеет свои нюансы. Перед выводом текста нужно установить параметры шрифта с помощью метода setFont, а с помощью метода textStyle задается цвет символов:

myPDF.setFont(FontFamily.HELVETICA, Style.BOLD_ITALIC, 18);
myPDF.textStyle ( new RGBColor ( 0xff0000 ) );

Следующий шаг - вызов метода writeText. Его параметры — это высота линии, сам текст и опциональная гиперссылка. В том случае, если третий параметр указан, то pdf-файл будет содержать не просто кусочек текста, но и гиперссылку на какой-либо сайт:

myPDF.writeText(50, "Click here to visit my site 1", "http://site.site");

Последующие вызовы метода writeText будут продолжать выводить текст на той же строке, пока она не закончится (либо вы явно прервете строку, выведя символ “\n”). Каждая из последующих строк будет начинаться с отступом относительно предыдущей в 50 мм. Так что, если указать недостаточную высоту линий, то выводимый текст сольется. Выводя текст, можно не беспокоиться о том, что для него не хватит высоты страницы: alivepdf автоматически начнет новую страницу, как только это потребуется. Еще один способ вывода текста – это метод addMultiCell. Он автоматически побеспокоится о переносах текста, если он не будет вмещаться в указанный вами прямоугольник шириной в 100 мм. Для того чтобы строки не сливались, я указал каждую новую строку начинать отступом от предыдущей в 10 мм. Четвертый
параметр включает отображение вокруг области текста прямоугольника границы. И последний параметр задает выравнивание текста по правому краю “R”.

myPDF.addMultiCell(100, 10, "Некоторый очень длинный текст", 1, "R");

В том случае, если вы хотите получить абсолютный контроль за позиционированием выводимого текста, то можно использовать метод setXY с указанием координат, перед тем как вы начнете печатать текст:

myPDF.setXY(10, 10);
myPDF.writeText(10, "Absolutely Positioned Text");

Большой пласт функциональности alivepdf связан с рисованием 2d-примитивов. В следующем примере я покажу, как можно нарисовать круг и прямоугольник (см. рис. 2). Сначала я вызвал метод lineStyle, который настраивает характеристики всех рисуемых в дальнейшем линий (цвет и толщина линий). Затем я включаю режим заливки фона рисуемых фигур методом beginFill (цвет фона). В арсенале AlivePdf есть как “высокоуровневые” функции, рисующие сразу всю фигуру целиком (в примере круг), так и рисующие фигуру из отдельных линий. Во втором случае я последовательно задаю координаты всех вершин полигона и завершаю рисование (функция end).

myPDF.lineStyle(new RGBColor(0x0000ff ), 2);
myPDF.beginFill(new RGBColor(0xff0000));
// рисуем круг
myPDF.drawCircle(100, 100, 50)
// рисуем прямоугольник
myPDF.moveTo ( 50, 50 );
myPDF.lineTo ( 100, 50 );
myPDF.lineTo ( 100, 100 );
myPDF.lineTo ( 50, 100 );
myPDF.end()
myPDF.endFill();

Более удобный способ рисования фигур-полигонов – это метод drawPolygone, единственным параметром для которого является массив с координатами вершин рисуемой фигуры:

myPDF.drawPolygone ([100, 100, 120, 100, 120, 120]);

Более полезной, чем “ручное” рисование фигур на pdf-листе, является функция внедрения внутрь pdf-документа подготовленных заранее картинок. Сначала я покажу подход, когда внутрь swf-файла внедряется двоичное представление картинки, а затем она рисуется на pdf-странице. Здесь важно помнить, что внедренные картинки в отличие от нарисованных вручную фигур представляют собой растровые картинки. А значит, увеличив масштаб просмотра до больших величин, у вас будет возможность “познакомиться” с отдельными пикселями, составляющими картинку. Для следующего примера я сначала добавил в исходный код приложения директиву “внедрить” в swf-файл содержимое файла “foxmoving.jpg”.

[Embed( source="/assets/foxmoving.jpg", mimeType="application/octet-stream" )]
private var foxImage:Class;

А теперь можно попросить alivepdf нарисовать эту картинку:

myPDF.addPage();
myPDF.addImageStream(new foxImage() as ByteArray,100, 100, 500, 500);

Первый параметр функции addImageStream очевиден – ссылка на картинку. Затем идут координаты места, где нужно нарисовать картинку, и размер прямоугольной области для этого. Также вы можете попросить alivepdf масштабировать изображение или превратить его в http-ссылку. Что касается поддерживаемых форматов изображений, то это только png и jpg. Есть еще одна методика рисования на pdf-листе, которая предполагает, что изображение будет скопировано с некоего flash-клипа или класса, производного от flash.display.DisplayObject (см. рис. 3). К примеру, flash- приложение, представляющее собой конструктор дизайна интерьера, может скопировать нарисованный на себе же проект квартиры в pdf-файл: myPDF.addImage(this, 0, 0, 0, 0, ImageFormat.PNG);

Параметры метода addImage сходны с теми, которые были у предыдущего метода рисования, – addImageStream: ссылка на DisplayObject, координаты, где будет нарисована картинка, затем размер прямоугольной области и формат картинки (png или jpg).

Последнее действие, которое будет выполнено после завершения подготовки pdf-файла, – это его сохранение. Во-первых, файл можно отправить для сохранения на сервер:

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- файл на e-mail.

В случае если вы создаете air-приложение, имеющее прямой доступ к файловой системе, то можно сохранить pdf-документ сразу на жесткий диск, например, так:

var f:FileStream = new FileStream();
var file: File = File.desktopDirectory.resolvePath("AliveDemo.pdf");
f.open(file, FileMode.WRITE);
var bytes:ByteArray = myPDF.save(Method.LOCAL);
f.writeBytes(bytes);
f.close();

Я специально останавливаюсь только на одной статье, рассказывающей о AlivePDF, так как возможностей по форматированию содержимого pdf-документа очень-очень много, а я не хочу ставить перед собой задачу написания малополезного супер-справочника. Достаточно того, чтобы вы понимали цель и сферу применения alivepdf, а в деталях использования, конкретных параметрах для конкретных функций можно разобраться, просто экспериментируя.

black-zorro@tut.by black-zorro.com


Компьютерная газета. Статья была опубликована в номере 34 за 2009 год в рубрике soft

©1997-2024 Компьютерная газета