четверг, 3 июня 2010 г.

PDF в Qt

Столкнулся со следующей задачей.

Нужно хранить некие данные (текст + графика) достаточно большого объема (~50 Мб) в одном файле.
Желательно, чтобы это был общедоступный формат типа XML, но чтобы его мог просмотреть неискушенный юзер.
То есть, данные в документе еще должны быть и оформлены красивым образом.
На ум приходят:
1) XML + XSL. Данные храним в XML, для отображения используем файл стилей. Минус — нет сжатия данных, вместо одного файла получаем два.
2) OpenDocument. Не работал с ним.
3) XPS файл.
4) PDF.


Сам больше склоняюсь к PDF. Как SDK можно использовать PoDoFo.
PDF хорош тем, что в нем есть криптование и сжатие.
Минусом является то, что в PDF нет тегов как в XML и как извлекать данные пока не представляю.
К тому же мы получается прописываем в этот файл одно оформление и поменять его на лету как в связке с XML+XSL не сможем.

В результате выбор был сделан с сторону храненения в PDF.
Схема взаимодействия примерно такая.

Формируем XML, включающий все нужные данные (графика в Base64). XML сериализуем и запихиваем в PDF аттачем. Отдельно же делаем вьюшку, которую оформляем нужным образом со всеми красивостями. То есть, в PDF будут находиться реальные данные в неискаженном виде (они будут невидимы) и некая выжимка, превьюшка, этих данных.
Соответственно нужно сгородить классы, которые будут все это реализовывать и не забыть синхронизировать данные и превьюшку при измнении.

Собственно встал вопрос - как же работать с PDF? Есть официальный SDK от Adobe и стоит он некисло баксов. Гугление привело на сайт PoDoFo (http://podofo.sourceforge.net/about.html).
PoDoFo is a library to work with the PDF file format. The name comes from the first letter of PDF (Portable Document Format). A few tools to work with PDF files are already included in the PoDoFo package.
  Сама библиотека podofo распространяется под LSPL, т.е. может быть использована в коммерческих целях, а ряд тулз в наборе под GPL, но нам они и не нужны.

Сборка PoDoFo отдельная песня.
Расскажу как это сделать под VS 2005.
Во-первых, надо скачать сам podofo (на момент написания статьи доступна версия 0.8.0 от 25.04.10).
Затем тащим библиотеку libjpeg (http://www.ijg.org/). Собираем либу. Выполням пару команд.
copy jconfig.vc jconfig.h && nmake /f makefile.vc /a

Тащим freetype (http://download.savannah.gnu.org/releases/freetype/)
Разворачиваем, собирать не понадобилось как ни странно.

Тащим zlib114dll (http://zlib.org/). Я тащил именно этот вариант. Т.к. с zlib125 или zlib123 ничего не вышло. Это уже собранные dll c h-файлом.

Все эти библиотечки кучкой сложены рядом друг с другом.
freetype-2.3.9
jpeg-8b
podofo-0.8.0
zlib114
Далее. Нам нужен CMake (http://www.cmake.org/HTML/Download.html).
Тащим, устанавливаем. Я ставил cmake-2.8.1-win32-x86.exe

Вроде все.
Начинаем сборку podofo.
Мне понадобилось набросать такой батничег build.cmd.
del cmakecache.txt
set FTDIR=E:\Work\3rd\freetype-2.3.9
set FTLIBDIR=E:\Work\3rd\freetype-2.3.9\objs\win32\vc2005
set JPEGDIR=E:\Work\3rd\jpeg-8b
set ZLIB_LIBRARY=E:\Work\3rd\zlib114\dll32\zlib.lib
set ZLIB_INCLUDE_DIR=E:\Work\3rd\zlib114
set PATH=E:\Work\3rd\zlib114\dll32;%PATH%
set PATH=E:\Work\3rd\zlib114;%PATH%

cmake -G "Visual Studio 8 2005" ..\podofo-0.8.0 -DCMAKE_INCLUDE_PATH="%FTDIR%\include;%JPEGDIR%\include;%JPEGDIR%;%ZLIBDIR%\include" -DCMAKE_LIBRARY_PATH="%FTLIBDIR%;%FTDIR%\lib;%JPEGDIR%\lib;%JPEGDIR%;%ZLIBDIR%\lib" -DPODOFO_BUILD_SHARED:BOOL=FALSE -DFREETYPE_LIBRARY_NAMES_DEBUG=freetype239MT_D -DFREETYPE_LIBRARY_NAMES_RELEASE=freetype239MT
 В итоге PoDoFo должно собраться и осчастливить появлением библиотеки podofo.dll.
До кучи будут собраны тесты и экземплы.

Все. Можно создавать PDF. Следующий код создаст PDF с надписью HELLO WORLD
  #include "podofo.h"
  using namespace PoDoFo;
  ...
  PdfStreamedDocument document("test.pdf");
  PdfPainter painter;
  PdfPage* pPage;
  PdfFont* pFont;
  pPage = document.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) );
  painter.SetPage( pPage );
  pFont = document.CreateFont( "Arial" );
  pFont->SetFontSize( 18.0 );
  painter.SetFont( pFont );

  painter.DrawText( 56.69, pPage->GetPageSize().GetHeight() - 56.69, "HELLO WORLD!");

  painter.FinishPage();
  document.Close();
 

* This source code was highlighted with Source Code Highlighter.

1 комментарий:

  1. А почему не использовать возможности предоставляемые самим QT? QGraphicsScene + QPrinter чудесно создают выходной pdf файл, если необходимо хранить внутри еще и не обработанные данные, то pdftk отлично позволит это сделать, хотя на мой взгляд удобнее для дальнейшей обработки просто иметь два файла file_name.pdf & file_name.xml Может объединенные в одни zip архив

    ОтветитьУдалить