Различные операционные системы все больше теснят MS Windows в технических заданиях. Часто все усугубляется пугающим в недалеком прошлом словом "кроссплатформенность". Многие задачи могут потребовать серьезной доработки для портирования под другую операционную систему. Повезет тем, кто изначально заложил в проект использование кроссплатформенных библиотек. Им портирование можно будет реализовать в несколько строк кода или добавлением директив компилятора. Одним из самых востребованных кроссплатформенных форматов электронных документов является формат PDF. Сегодня я рассмотрю несколько вариантов создания файлов в этом формате под Windows и Linux. Но они подойдут и для других операционных систем.
Первый вариант – это использование библиотеки Foxit Quick PDF Library (бывшая Debenu Quick PDF Library). Foxit Quick PDF Library предоставляет разработчику полный спектр функций для создания и манипулирования файлами формата PDF под Windows, Mac, Linux, iOS и Android. Сразу скажу, что это удовольствие не из дешевых. Библиотека лицензируется отдельно под каждую операционную систему, и лицензия на одного разработчика стоит $499. Я не рассматриваю бесплатную Quick PDF Library Lite по двум причинам: во-первых, у нее нет версий под Linux и Android, а во-вторых, она не обновлялась с начала июня 2015-года и содержит давно устаревшие версии (11.14 под Windows и 11.15 под Mac/iOS). У Foxit Software есть еще Foxit PDF SDK, который существовал до покупки ими компании Debenu. Но его я тоже не буду рассматривать, так как на это тоже есть две причины: во-первых, у него нет версии под Delphi, а во-вторых, его цена на одного разработчика $3 000.
Quick PDF Library for Windows включает в себя:
Quick PDF Library for Linux поставляется в скомпилированном виде и поддерживает 64-разрядные версии Ubuntu, CentOS и Debian. Не повторяйте мою ошибку и не пытайтесь сами ее прикрутить к проекту на Delphi. Для экономии вашего времени сразу требуйте у разработчиков pascal'евский модуль с классом, который является оберткой для вызова функций библиотеки. Судя по комментарию в тексте, он "macOS Edition".
Теперь приведу пример небольшой тестовой программы. Она создает простой PDF файл содержащий текст, написанный разными шрифтами, линию, картинку и гиперссылки.
Второй вариант, для тех, у кого бюджет проекта не позволяет заложить $1000 на дополнительные библиотеки. Посмотрите внимательно на библиотеки, которые уже есть в вашем распоряжении. Например, мне пришла мысль воспользоваться имеющейся у меня библиотекой TMS FlexCel. Про TMS FlexCel тоже можно сказать "предоставляет разработчику полный спектр функций для создания и манипулирования файлами под Windows, Mac, Linux, iOS и Android". Только формат этих файлов не PDF, как нам надо, а MS Excel. Но библиотека TMS FlexCel включает в себя модуль для конвертации файлов из формата MS Excel в PDF. Нас не интересует его основной класс TFlexCelPdfExport, который на "высоком уровне" может преобразовывать файлы. Нас интересует класс TPdfWriter, который представляет собой API для создания документов в формате PDF. Как работать с TMS FlexCel под Linux я уже описывал раньше, поэтому сразу перейду к примеру программы:
Размер скомпилированной тестовой программы (в мегабайтах):
* Дополнительные файлы: для Quick PDF Library – libFoxitQPL1811-linux-x64.so (сама библиотека), а для TMS FlexCel – libflexskia.so.4 (open-source библиотека Skia для работы с 2D-графикой).
Функциональные возможности TPdfWriter из TMS FlexCel, по сравнению с Quick PDF Library, небольшие, но их вполне хватает для создания простых документов в формате PDF. Стоимость TMS FlexCel на сегодняшний день €175 или $264.52 (в пересчете сайта TMS). Таким образом, поддержка экспорта в формат PDF для Windows и Linux с ее использованием будет стоить в четыре раза дешевле, чем с использованием Foxit Quick PDF Library.
Многие библиотеки имеют свои классы для экспорта в PDF формат. Изучая, в процессе написания этой статьи, сайт компании TMS Software, я нашел, что TMS VCL UI Pack (бывший TMS Component Pack) включат в себя библиотеку для создания документов в формате PDF – TAdvPDFLib. Я не уверен, что TAdvPDFLib можно скомпилировать под Linux, но в TMS FMX UI Pack есть кроссплатформенный TTMSFMXPDFLib. Таким образом не спешите покупать новые библиотеки, а хорошо изучите те, что уже имеете. Возможно их функций будет достаточно для вашей новой задачи.
Первый вариант – это использование библиотеки Foxit Quick PDF Library (бывшая Debenu Quick PDF Library). Foxit Quick PDF Library предоставляет разработчику полный спектр функций для создания и манипулирования файлами формата PDF под Windows, Mac, Linux, iOS и Android. Сразу скажу, что это удовольствие не из дешевых. Библиотека лицензируется отдельно под каждую операционную систему, и лицензия на одного разработчика стоит $499. Я не рассматриваю бесплатную Quick PDF Library Lite по двум причинам: во-первых, у нее нет версий под Linux и Android, а во-вторых, она не обновлялась с начала июня 2015-года и содержит давно устаревшие версии (11.14 под Windows и 11.15 под Mac/iOS). У Foxit Software есть еще Foxit PDF SDK, который существовал до покупки ими компании Debenu. Но его я тоже не буду рассматривать, так как на это тоже есть две причины: во-первых, у него нет версии под Delphi, а во-вторых, его цена на одного разработчика $3 000.
Quick PDF Library for Windows включает в себя:
- DCU для Delphi 4-10.4 (32/64 бита);
- DLL для C, Visual C++, C++ Builder, C#, Delphi, Visual Basic, Python... (32/64 бита);
- ActiveX для C#, Visual C++, C++Builder, Delphi, Visual Basic, PHP, Python, Java, PowerBASIC... (32/64 бита);
- LIB для 32-битных C/C++.
Quick PDF Library for Linux поставляется в скомпилированном виде и поддерживает 64-разрядные версии Ubuntu, CentOS и Debian. Не повторяйте мою ошибку и не пытайтесь сами ее прикрутить к проекту на Delphi. Для экономии вашего времени сразу требуйте у разработчиков pascal'евский модуль с классом, который является оберткой для вызова функций библиотеки. Судя по комментарию в тексте, он "macOS Edition".
Теперь приведу пример небольшой тестовой программы. Она создает простой PDF файл содержащий текст, написанный разными шрифтами, линию, картинку и гиперссылки.
program fqPdf; {$APPTYPE CONSOLE} uses System.SysUtils, {$IFDEF MSWINDOWS} DebenuPDFLibrary {$ELSE} FoxitQPLDylib {$ENDIF}; const {$IFDEF MSWINDOWS} csKey = 'key for Windows'; {$ELSE} csKey = 'key for Linux'; {$ENDIF} procedure Test; var {$IFDEF MSWINDOWS} pdf: TDebenuPDFLibrary; {$ELSE} pdf: TFoxitQPLDylib1811; {$ENDIF} FontArial: Integer; begin {$IFDEF MSWINDOWS} pdf := TDebenuPDFLibrary.Create; {$ELSE} pdf := TFoxitQPLDylib1811.Create('libFoxitQPL1811-linux-x64.so'); {$ENDIF} try if pdf.UnlockKey(csKey) = 1 then begin pdf.NewDocument; pdf.SetPageSize('A4'); pdf.SetOrigin(1); // добавляем шрифт для дальнейшего использования FontArial := pdf.AddTrueTypeFont('Arial', 0); // зеленая линия pdf.SetLineWidth(0.86); pdf.SetLineColor(0, 0.5, 0); pdf.DrawLine(20, 10, 355, 10); // черный текст Arial 14 pdf.SelectFont(FontArial); pdf.SetTextSize(14); pdf.SetTextColor(0, 0, 0); pdf.DrawText(95, 30, 'BlackCat'); // синий подчеркнутый текст Times New Roman 15.5 курсив // pdf.AddTrueTypeFont('Times New Roman [Italic]', 0); pdf.AddStandardFont(10); // TimesItalic pdf.SetTextSize(15.5); pdf.SetTextColor(0, 0, 1); pdf.SetTextUnderline(1); // Single pdf.DrawText(155, 30, 'https://it-blackcat.blogspot.com'); // добавляем изображение и делаем его ссылкой var imgID: Integer := pdf.AddImageFromFile('BlackCat.jpg', 0); pdf.SelectImage(imgID); pdf.DrawImage(20, 15, 70, 64); pdf.AddLinkToWeb(20, 15, 70, 64, 'https://it-blackcat.blogspot.com', 0); pdf.CompressContent; pdf.SaveToFile('test.pdf'); end else WriteLn('The license key is invalid or has expired') finally pdf.Free; end; end; begin ReportMemoryLeaksOnShutdown := True; try Test; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.Как видите, несколько директив компилятора и программа стала кроссплатформенной. Для большего сходства с версией под Windows в FoxitQPLDylib я добавил класс TDebenuPDFLibrary, который унаследовал от TFoxitQPLDylib1811. Класс содержит только конструктор, который инициализирует библиотеку без указания ее имени. Что бы в будущем не менять модуль я переименовал libFoxitQPL1811-linux-x64.so в libFoxitQPL-linux-x64.so. Никогда не мог понять, зачем авторы Quick PDF Library всегда в название классов вставляют номер ее версии.
type TDebenuPDFLibrary = class (TFoxitQPLDylib1811) constructor Create; end; implementation constructor TDebenuPDFLibrary.Create; begin inherited Create('libFoxitQPL-linux-x64.so'); end;Теперь программе понадобилось меньше директив:
program fqPdf; {$APPTYPE CONSOLE} uses System.SysUtils, {$IFDEF MSWINDOWS} DebenuPDFLibrary {$ELSE} FoxitQPLDylib {$ENDIF}; const {$IFDEF MSWINDOWS} csKey = 'key for Windows'; {$ELSE} csKey = 'key for Linux'; {$ENDIF} procedure Test; var pdf: TDebenuPDFLibrary; FontArial: Integer; begin pdf := TDebenuPDFLibrary.Create; ...Если сравнить результат работы программы под Linux и результат работы программы под Windows то вы не сможете найти различия. Ссылки на обеих картинках — это всплывающая подсказка в Acrobat Reader. Они оставлены на картинках для того, чтобы продемонстрировать, что программа создала ссылки.
Второй вариант, для тех, у кого бюджет проекта не позволяет заложить $1000 на дополнительные библиотеки. Посмотрите внимательно на библиотеки, которые уже есть в вашем распоряжении. Например, мне пришла мысль воспользоваться имеющейся у меня библиотекой TMS FlexCel. Про TMS FlexCel тоже можно сказать "предоставляет разработчику полный спектр функций для создания и манипулирования файлами под Windows, Mac, Linux, iOS и Android". Только формат этих файлов не PDF, как нам надо, а MS Excel. Но библиотека TMS FlexCel включает в себя модуль для конвертации файлов из формата MS Excel в PDF. Нас не интересует его основной класс TFlexCelPdfExport, который на "высоком уровне" может преобразовывать файлы. Нас интересует класс TPdfWriter, который представляет собой API для создания документов в формате PDF. Как работать с TMS FlexCel под Linux я уже описывал раньше, поэтому сразу перейду к примеру программы:
program fcPdf; {$APPTYPE CONSOLE} uses System.Classes, System.SysUtils, {$IFDEF MSWINDOWS} VCL.FlexCel.Core {$ELSE} SKIA.FlexCel.Core {$ENDIF}, FlexCel.Pdf; procedure Test; var pdf: TPdfWriter; fs: TFileStream; FontArial: TUIFont; BrushBlack: TUISolidBrush; Underline: TUITextDecoration; Brush: TUISolidBrush; begin pdf := TPdfWriter.Create; try fs := TFileStream.Create('test.pdf', fmCreate); try // добавляем шрифт для дальнейшего использования FontArial := TUIFont.CreateNew('Arial', 14, []); try BrushBlack := TUISolidBrush.CreateNew(Colors.Black); try Underline := TUITextDecoration.Create(TUIUnderline.Single); pdf.Compress := True; pdf.YAxisGrowsDown := True; pdf.BeginDoc(fs); try // зеленая линия var pen: TUIPen := TUIPen.CreateNew(Colors.Green); try pdf.DrawLine(pen, 20, 10, 355, 10); finally pen.Free; end; // черный текст Arial 14 pdf.DrawString('BlackCat', FontArial, BrushBlack, 95, 30); // синий подчеркнутый текст Times New Roman 15.5 курсив Brush:= TUISolidBrush.CreateNew(Colors.Blue); try var FontTimes: TUIFont := TUIFont.CreateNew('Times New Roman', 15.5, [TUIFontStyle.fsItalic]); try pdf.DrawString('https://it-blackcat.blogspot.com', FontTimes, Underline, Brush, 155, 30); finally FontTimes.Free end; finally Brush.Free; end; // добавляем изображение и делаем его ссылкой pdf.Hyperlink(20, 15, 70, 64, 'https://it-blackcat.blogspot.com'); var img: TUIImage := TUIImage.FromFile('BlackCat.jpg'); try pdf.DrawImage(img, TUIRectangle.Create(20, 15, 70, 64), nil); finally img.Free; end; finally pdf.EndDoc; end; finally BrushBlack.Free end; finally FontArial.Free end; finally fs.Free end; finally pdf.Free end; end; begin ReportMemoryLeaksOnShutdown := True; try Test except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.Приведу одну картинку с результатами, т.к. они опять под Windows и под Linux совпадают между собой: Как вы видите результат работы TPdfWriter из TMS FlexCel очень похож на результат Quick PDF Library. Единственное, еле заметное отличие – это то, что у надписи курсивом местами немного не совпадают расстояния между буквами.
Размер скомпилированной тестовой программы (в мегабайтах):
Библиотека | Windows | Linux | ||
Программа | Дополнительные файлы * | Суммарно | ||
Quick PDF Library | 7.73 | 1.11 | 20.00 | 21.11 |
TMS FlexCel | 3.17 | 8.01 | 5.41 | 13.42 |
Функциональные возможности TPdfWriter из TMS FlexCel, по сравнению с Quick PDF Library, небольшие, но их вполне хватает для создания простых документов в формате PDF. Стоимость TMS FlexCel на сегодняшний день €175 или $264.52 (в пересчете сайта TMS). Таким образом, поддержка экспорта в формат PDF для Windows и Linux с ее использованием будет стоить в четыре раза дешевле, чем с использованием Foxit Quick PDF Library.
Многие библиотеки имеют свои классы для экспорта в PDF формат. Изучая, в процессе написания этой статьи, сайт компании TMS Software, я нашел, что TMS VCL UI Pack (бывший TMS Component Pack) включат в себя библиотеку для создания документов в формате PDF – TAdvPDFLib. Я не уверен, что TAdvPDFLib можно скомпилировать под Linux, но в TMS FMX UI Pack есть кроссплатформенный TTMSFMXPDFLib. Таким образом не спешите покупать новые библиотеки, а хорошо изучите те, что уже имеете. Возможно их функций будет достаточно для вашей новой задачи.
Для генерации PDF использую FastReport. Под Linux правда приходится использовать Lazarus, но возможности полноценного генератора отчётов перевешивают все сложности первоначального вхождения.
ОтветитьУдалитьТоже пользуюсь FastReport для генерации PDF. Delphi - Windows.
ОтветитьУдалитьПро использование FastReport для генерации PDF, я тоже думал написать. У меня был такой опыт :) Кстати, я об этом писал ровно 10 лет тому назад - https://it-blackcat.blogspot.com/2011/02/fastreport-pdf.html
ОтветитьУдалитьНо не написал в этой статье по трем причинам:
1. Я писал про Windows и Linux, а тут информация о Linux на сайте производителя противоречивая. На странице FastReport FMX 2 написано "Multi platform Report Generator for Apple Mac OS X and Microsoft Windows", хотя в анонсе FastReport FMX 2.8 написано "added FmxLinux support". Поддержка Linux добавлена меньше месяца тому назад, значит, как она работает еще не известно. К тому же черновик статьи я написал еще в прошлом году.
2. FastReport зажат рамками шаблонов - это не подходило под мою задачу. Хотя я не изучал исходный текст экспорта FastReport, не исключено, что им можно воспользоваться, как TPdfWriter у FlexCel.
3. В статье я пишу "не спешите покупать новые библиотеки, а хорошо изучите те, что уже имеете". Т.е. я рассмотрел то, что я имею и использую давно: Debenu Quick PDF Library и TMS FlexCel. Для исследования темы экспорта в PDF у меня нет FastReport FMX. Да и лицензия на FastReport VCL закончилась на какой-то из Delphi XE (все как-то не судьба опять поработать с FastReport).
1. FMX только Windows и OS X. Для чистого Linux либо VCL, либо Mono. Но в Mono особо смысла не вижу, так как под Linux вполне уже работает майкрософтовский .CORE 3.1.
Удалить2. Шаблоны да, правда. Но в особо извращённых случаях их можно рисовать из кода "на лету". "Чистого" TPDFWrite'а тут конечно нет, но т.к. есть исходный код, всё в наших руках.
3. Я ни в коем разе не призываю "все на FR" :), просто пользуюсь им очень давно (ещё с версии 2.0). Он покрывает 100% моих потребностей формирования форматированных страниц. И когда в нём появился экспорт в PDF это закрыло вообще все остававшиеся дыры.
Последние годы, так сошлись звёзды, мне приходится активно работать с системой написанной на Perl (Debian). И "внезапно" там потребовался экспорт в PDF всевозможных документов, генерируемых системой. Потратив немного времени, скрестил ежа с ужом и теперь у меня есть FastReport под Perl ;). Это я к тому, что при желании FR можно прикрутить почти куда угодно.
А бесплатный mORMot с задачей не справился бы?
ОтветитьУдалитьМожет и справился бы. О mORMot и SynPDF я даже не знал :) Спасибо за информацию. Освятить вариант с бесплатной библиотекой я не подумал (я больше доверяю проприетарному софту).
УдалитьОбъясню, чем обусловлен выбор библиотек в статье - я как акын "что вижу, о том и пою". Проект был реализован под Windows с использованием Quick PDF и FlexCel. При переводе его на Linux отсутствие Quick PDF Delphi Edition под Linux сильно опечалило заказчика. TPdfWriter у FlexCel - это как пример того, что прямо под носом есть доступные кроссплатформенные альтернативы Quick PDF, которые заточены под Delphi. В реальности же в том проекте уйти с Quick PDF малой кровью не получится. Quick PDF прикручен к TMS Scripter и при смене генератора PDF нужно кому то будет переписывать скрипты, которые генерируют PDF-файлы. Плюс используются функции, которых у TPdfWriter нет. Например, экспорт созданного PDF в картинку. Поэтому вариант "libFoxitQPL-linux-x64.so + TFoxitQPLDylib1811" - это выход.
P.S. Если говорить не только об создании PDF, но и о его парсинге, то, как мне кажется, Quick PDF - это хороший (а может и лучший) выбор.
Спасибо! Пользуюсь FlexCel много лет, но не думал, что его можно использовать для генерации PDF.
ОтветитьУдалитьВы написали, что "предоставляет разработчику полный спектр функций ... и Android". На сайте https://www.quickpdflibrary.com/products/quickpdf/index.php нет "Android". В Delphi под Windows компилится, а для android требует Unit DebenuPDFLibrary1811, есть только *.dcu. Заработает с исходниками?
ОтветитьУдалитьПод Android собирать QuickPDF из исходников Delphi Edition нельзя. Foxit Quick PDF Library for Android - это библиотеки на С++ и юнита FoxitQPLAndroid1811.pas, которая содержит класс TFoxitQPLAndroid1811 с вызовами функций из библиотеки.
Удалить