pax_global_header00006660000000000000000000000064134315462460014522gustar00rootroot0000000000000052 comment=be0974c08b75495662ae36ae05735fda8cd153ec wkhtmltopdf-0.12.5/000077500000000000000000000000001343154624600141525ustar00rootroot00000000000000wkhtmltopdf-0.12.5/.gitignore000066400000000000000000000003361343154624600161440ustar00rootroot00000000000000# ignore mac build files build/ *.plist *~ \#*\# bin wkhtmltopdf.app/ wkhtmltopdf.xcodeproj/ release*/ test/ static-build/ .obj/ doc/ libdoc/ man1/ Makefile qrc_wkhtmltopdf.cpp Makefile.* *_resource.rc *.o moc_*.* .qmake* wkhtmltopdf-0.12.5/.gitmodules000066400000000000000000000001101343154624600163170ustar00rootroot00000000000000[submodule "qt"] path = qt url = ../qt.git branch = wk_4.8.7 wkhtmltopdf-0.12.5/.travis.yml000066400000000000000000000032611343154624600162650ustar00rootroot00000000000000language: cpp dist: trusty sudo: required notifications: email: false services: - docker matrix: include: - os: linux env: TARGET=system-qt4-linux addons: apt: packages: - libqtwebkit-dev - os: linux env: TARGET=system-qt5-linux addons: apt: packages: - libqt5webkit5-dev - libqt5xmlpatterns5-dev - libqt5svg5-dev - os: linux env: TARGET=custom-qt4-linux - os: osx osx_image: xcode9.3 env: TARGET=custom-qt4-osx - os: linux env: TARGET=custom-qt4-windows install: - sed -i -e 's/ SYNCQT_OPTS=/ SYNCQT_OPTS=-quiet/g' qt/configure - test -n "$CC" && unset CC - test -n "$CXX" && unset CXX - git clone https://github.com/wkhtmltopdf/packaging.git ../packaging script: - > if [[ $TARGET == "system-qt4-linux" ]]; then qmake-qt4 CONFIG+=silent && make; elif [[ $TARGET == "system-qt5-linux" ]]; then /usr/lib/x86_64-linux-gnu/qt5/bin/qmake CONFIG+=silent && make; elif [[ $TARGET == "custom-qt4-linux" ]]; then ../packaging/build compile-docker stretch-amd64 $PWD ../build; elif [[ $TARGET == "custom-qt4-windows" ]]; then ../packaging/build compile-docker mxe-cross-win64 $PWD ../build; elif [[ $TARGET == "custom-qt4-osx" ]]; then sudo -H pip install -q conan pyyaml --ignore-installed six && sudo gem install fpm --no-ri --no-rdoc && \ sudo xcode-select --switch /Library/Developer/CommandLineTools && \ MACOSX_DEPLOYMENT_TARGET=10.7 ../packaging/build vagrant macos-cocoa --clean --version - - $PWD; fi wkhtmltopdf-0.12.5/AUTHORS000066400000000000000000000063751343154624600152350ustar00rootroot00000000000000 Jakob Truelsen Ashish Kulkarni Jan Habermann Pablo Ruiz García Trevor North Nate Pinchot pussbb Aaron Stone Patrick Widauer @a-ctor Peter van der Tak Benjamin Sinkula Kasper F. Brandt Michael Nitze Rok Dvojmoc theirix Artem Butusov Christian Sciberras Daniel M. Lambea Douglas Bagnall peterrehm Renan Gonçalves Ruslan Grabovoy Sander Kleykens Adam Thorsen Albin Kerouanton Alejandro Dubrovsky Arthur Cinader @acinader Benoit Garret Bill Kuker cptjazz daigot Destan Sarpkaya @destan Duncan Smart Emil Lerch Erik Hyrkas Erling Linde Fábio C. Barrionuevo da Luz Fr33m1nd Frank Groeneveld Immanuel Häussermann Jake Petroules James Macdonald Jason Smith John Muccigrosso @Jmuccigr Julien Le Goff Kay Lukas Kurt Revis laura @holamon Marc Laporte Matthew M. Boedicker Matthieu Bontemps Max Sikstrom Nolan Neustaeter Oleg Kostyuk Pankaj Jangid robinbetts Sem Stefan Weil Stephen Kennedy Steve Shreeve Sven Nierlein Tobin Juday Todd Fisher Костадин Дамянов Emmanuel Bouthenot rainabba Mehdi Abbad Lyes Amazouz Pascal Bach Mário Silva wkhtmltopdf-0.12.5/CHANGELOG-OLD000066400000000000000000000222631343154624600160050ustar00rootroot00000000000000v0.11.0 rc2: * #354: Proper handling of directly embedded grayscale jpeg images * #429: output filenames interperted as latin1 instead of utf8 * #441: Gif images do not work * #463: Null byte in anchor name * #635: Make /dests an indirect object * #730: Do not assume that QPixmap requiers GUI v0.11.0 rc1: * #149: Use base url to resolve links * #667: Expose load settings in image c binding * #707: Relative links are converted to absolute links * Update to newer version of qt v0.10.0 rc2: * Relicense under LGPL * #349: HTTP POST format * #365: isLoaded Flag * #414: Release bz2 files instead of xz files * #426: Reenable --page-offset * #428: toimage buffer does no work v0.10.0 rc1: * #171, #307: Javascript does not work well in i386 static binaries * #226, #326: Absolute path are broken on windows * #310: Sections in headers only work for the first document * #315: Allow arbitrery javascript to be run * #332: Also used names to resolve local links * #333: Segmentation fault when plugins are not enabled * #345 double escaping of html entries in toc * Partly #366: allow for custum SVG for checkboxes and radio button * #378: the -n switch is ambigius * Fix issue: Do not include covers in the outline and toc v0.10.0 beta5: * Create a libwkhtmltox an relicense under LGPL * Add missing --header-line switch * #271: Image quality in wkhtmltoimage is not good when using --zoom. * #286: Outlines have incorrect page numbers * #288: -s, --page-size command line switch broken * #328: Ignores supplied xsl stylesheet for to v0.10.0 beta4: * Added wkhtmtoimage to the source tree, thanks to Christian Sciberras. * Added width parameter to wkhtmloimage * Added svg support to wkhtmlimage * Command line layout reworked * Allow for options to be parsed on a per page section * Table of content is now generated via XSLT * Updated to use QT 4.7 * Mac binary no longer displayes in dock. * #72: the font spacing issues on linux solved when using --use-xserver * #55: wkhtmltopdf dies on unavaliable url or network disconnection * #114: Add option to for not loading images. * #122: No output to stderr describing HTTP 500 server error * #143: Add wkhtmltoimage * #144: User stylesheet is not working * #161: Better image handling * #170: Allow for table of content to be placed anywhere * #184: wkhtmltopdf crashes with rigt to left texts. * #188: Allow for greater TOC customization * #205: Add support for local timezone in creation date * #238: Add option to force output format * #244: Outline contains headers from hidden content * #249: Spelling * #258: Likns and references to the right pages. * #265: mingwm10.dll is empty * #267: Sizing problem with wkhtmltoimage and page with no particular width * #268: --scale-w doesn't work as expected * #270: Do not print crosses and circles in ALL the form fields * #273: (Hack) Do not draw the content of a textbox when using forms * #278: wkhtmltoimage exits with none existing http error codes. * #280: Incorrect page numbering * Implement issue 281: Support of page title in header/footer * #284: Wrong width when dealing with an invalid html file v0.9.7 * Fix bug: Use \- some more places in the man page. * #220: Allowing the good load check to be disabled. * #223: Replace date and time in headers and footers. * #225: Add support for links in headers and footers. v0.9.6 * #191: Add support for not compressing pdf. * #210: PATH is overridden by windows 7 install * #228: Unable to use none ASCII pdf titles * Add nicer rendering for text fields and checkboxes * Added initial support for HTML forms v0.9.5 * #196: Unable to use none ASCII file names. * Fix multiple issues with links in the pdf file v0.9.4 * Fix --toc-header-font-size implementation, added --toc-header-font-name * Added a --dump-outline option (Patch by Douglas Bagnall) * Added a minimal font size option (Patch by Dmitry Teslenko) * Fix pdf outline parent ID (Patch by Douglas Bagnall) v0.9.3 * #141: wkhtmltopdf does not terminate properly on OSX. (Jan Harbermann) * #176: Properly escape strings in the pdf engine. (Patch by Douglas Bagnall) * #181: Properly encode string in pdf outline. (Patch by Douglas Bagnall) * Fix some spelling in the manual v0.9.2 * #160: Handle slow scripts instead of terminating with a no X warning. The new default is to just let the scripts run for as long as they want. Unless --stop-slow-scripts is specified. * #164: Text read from standard in is interpreted as ASCII, not as local 8bit. (utf8) * #165: Add a title to the pdf document. * Fix page numbers in TOC when pageOffset has been specified. * Fixed faults in documentation. * Handle javascript alert, confirm and prompt gracefully. * Added a switch --debug-javascript to output javascript errors and warnings to stderr. v0.9.1 * Added change log to release tar ball * Fixed up man page * #140: --disable-javascript shod not affect --header-html * #142: We now wait for --redirect-delay microseconds before printing a page, allowing for javascript redirects to occur, or dynamic content to be generated. However if a window.print() javascript statement is executed we wait no longer. * #147: Detect if --header-html is html * #155: Cookie support is broken * Add support for userdefined replacements in headers and footers. * Fix bug where the header line would not be horizontal v0.9.0 * Complete code rewrite. * Add support for HTML headers and footers. * Do not exit 0 when a 404 has occurred * Added a manual/readme * Added an installer under windows * #47: Give better error message if destination is not writeble * #56: with checkboxes printed badly * #61: PDF's send to stdout are broken on windows * #74: Scale of output is not fixed * #92: Support space between headers and contest * #125: Html documents from stdin does not work under windows * Allow headers and footers to be utf8 * Add zoom support * Add support for internal and external links * Add links and back links to the table of content * Links in the table of content, and outline now point at the correct location. * Fixed multiple issues with wrong TOC and outlines * Add support for custom HTML headers * Add support for loading and saving cookies * Add support for POST requests * Make static build work with older versions of libc * Much more that I have now forgotten. * Add support for custom page sizes * Upgrade to qt4.6 fixing issues with not being able to copy text in acroread * Upgrade to qt4.6 fixing issues with only one font family working. v0.8.3 * Allow custom page numbering (patch by Refael Bedia) * Add options to support HTTP authentication * Fix yet another leek in batch mode (patch by Mário Silva) * #when compiling with OT4.4 * #regarding X11 with unpatched Qt v0.8.2 * #with batch mode (patch by Mário Silva) * #with locale support in units * Added optional support for using X11 server, try this if no X11 fails. * Attempt to add support for NS Plugins * Fix issues when compiling with GCC 4.4 v0.8.1 * Static Linux version no longer requires X11 v0.8.0 * Added support for changing default input encoding (static binary only) * Added support for supplying user style sheet v0.7.5 * Fixed bug with proxy not working as it should * Added proxy information to the man page * Corrected some spelling v0.7.4 * Fixed bug: stdin input does not work, stdout does not work on windows * Fixed bug: minus not minus on a man page v0.7.2 * Fixed bug: Unable to compile with CMake * Default to printing in screen media-type, switch added to restore old default paper (static binary only) * Added an experimental windows executable * Fixed bud: Logic invertion in --disable-javascript v0.7.1 * Fixed bug: h1 and h6 not included in outline * Fixed bug: Page calculation not correct for none toplevel h1 tags * Fixed bug: Outline page coordinates are wrong (and inverted) * Fixed bug: Outline depth setting has no effect v0.7.0 * Added support for pdf outlines (static version only) * Added support for cover pages (static version only) * Added support for Table of Contents (static version only) * Added support for putting multiple files into one pdf (static version only) * Extensive rewrite of the argument parsing code * Several arguments have been renamed * Added support for disabling javascript v0.6.4 * Fix a bug regarding writing pages to stdout * Fixed spelling v0.6.2 * Fixed bugs regarding header and footer line in static build * Made the qmake file generate and install manpage * The Source tarball now actually contains the source v0.6.1 * Added a manpage * Fixed bug that disabled local page support * Update: The static binary has now been fixed. v0.6 * Added support for headers and footers (static binary only) * Added support for js-redirects * More code documentation added v0.5 * Added support for reading command line options from stdin, to do multiple conversions fast. * Added options to set page margins. * Now shipping a binary statically compiled against QT4.5rc1, that shuld run as is on just about any Linux System. v0.4 * Added support for generation deb packages * Added option for dpi, low resolution and grayscale * Added (untested) support for removing background image when running under QT 4.5 v0.3 * Added support for printing sites with self signed certificates * Added options for pageSize and orientation v0.2 * Added proxy support * Commandline parsing and quiet support v0.1.1 * Initial release wkhtmltopdf-0.12.5/CHANGELOG.md000066400000000000000000000223121343154624600157630ustar00rootroot00000000000000v0.12.5 (2018-06-11) -------------------- * fixed build without patched Qt and integrate with Travis CI and AppVeyor * **#1524**: **[qt]** partial fix for overlapping text when repeating headers/footers in table (qt#29) * **#1914**: **[qt]** rotated elements not rendered on thead on second page and beyond * **#1870**: fixed sending of duplicate cookies (#3257) * **#2609**: add viewportSize property to C API (#3440) * **#2711**: fix differences between "counting" and "printing" phases (causing crashes/blank pages) * **#3001**: fix static builds not working with updated OpenSSL * **#3090**: added support for SSL client certificates (#3206) * **#3241**: fix for DPI regression on OS X (#3386) * **#3363**: added error message for network errors related to non-media files * **#3364**: new option `verbosity` to allow different log levels in both CLI and API * **#3476**: fix application name in libwkhtmltox (#3878) * **#3672**: **[qt]** fix broken PDF with fonts having spaces in name (qt#38) * **#3680**: **[qt]** fix build on macOS 10.13 * **#3900**: **[qt]** properly encode URLs with unicode characters in links * add outlineDepth property to C API (#3291) * add wkhtmltoimage_destroy_global_settings method to C API (#3324) * switch to self-hosted website and downloads as gna.org is shutting down (#3390) * fix conversion of read-only form fields (#3550) * flush stderr to allow reading progress updates (#3583) * fix handling of errors for media URLs with query string (#3593) * add setting to perform hostname lookup via proxy (#3628) * correctly pass --copies to underlying QPrinter (#3747) * minor documentation updates and fixing compiler warnings * add various Qt patches to support OpenSSL 1.1 and latest MinGW/macOS environments * removed build scripts in favor of separate repo (wkhtmltopdf/packaging) v0.12.4 (2016-11-22) -------------------- * add support for building with VS2015 * update OpenSSL to 1.0.2j and libpng to 1.6.26 * **[qt]** change screen size in headless mode to a more sane value (1366x768) * **[qt]** allow screen size in headless mode to be overriden via environment variables * **[qt]** fix compilation failure on OS X 10.11 due to usage of deprecated APIs * **#1768**: allow using long argument list (without hardcoded limits) * **#2004**: **[qt]** fix rendering of form fields in PDF output * **#2353**: **[qt]** context.setLineDash doesn't work in Canvas * **#2416**: make background transparent by default for headers/footers * **#2463**: **[qt]** standardize rendering DPI to 96 * **#2673**: fail immediately in the build script if the Qt source is not available * **#2684**: **[qt]** fix crash in WebKit (RenderBlock::removeFloatingObjectsBelow) * **#2885**: enforce UTF-8 encoding for input strings in the API * **#2887**: improve docs to make examples of header/footer variables more explicit * **#3077**: use correct install path for man pages v0.12.3 (2016-01-20) -------------------- * **[qt]** upgrade the patched Qt to the last Qt 4.8 commit * removed support for CentOS 5 builds * update OpenSSL to 1.0.2e and xz to 5.2.2 and libjpeg to 9b * downgrade libpng to 1.2.56 * **#1843**: add --keep-relative-links and --resolve-relative-links to resolve relative links * **#1981**: fix temporary PDF files not being removed when writing to stdout * **#2104**: renamed COPYING to LICENSE * **#2183**: apply --javascript-delay settings for non-main resource loaders * **#2190**: do not depend on ICU even if it is already installed * **#2194**: **[qt]** fix debugging of Qt/WebKit due to missing debug information * **#2214**: **[qt]** fix broken rendering of transparent images when converting to PDF * **#2252**: fix ownership of /usr/local being changed during installation on OS X * **#2280**: do not allow data URIs for --header-html or --footer-html * **#2322**: fix broken debug builds with MSVC * **#2355**: add support for proxy bypass for specific hosts with --bypass-proxy-for * **#2418**: fix build error on OS X * **#2560**: allow using email address as proxy username * **#2572**: fix incorrect version detection when building distro-specific packages v0.12.2.1 (2015-01-19) ---------------------- * update OpenSSL to 1.0.1l * **#2084**: **[qt]** make background transparent by default when rendering to PDF * **#2142**: fix wkhtmltoimage ignoring --javascript-delay and --window-status * **#2151**: **[qt]** fix PDFs rendering without embedded fonts on 64-bit Cocoa build v0.12.2 (2015-01-09) -------------------- * external libraries updated: OpenSSL to 1.0.1k, libpng to 1.5.21 and xz to 5.2.0 * fix build failure with unpatched Qt >= 5.3 * **#1539**: **[qt]** using OpenType fonts now results in selectable text on Windows * **#1638**: **[qt]** fix incorrect rendering of JPEG images on Windows Server 2008 x64 * **#1639**: block access to local files on Windows when an invalid URL is used * **#1640**: **[qt]** make table page-break logic opt-in via CSS at the row level * **#1676**: do not allow overriding the header/footer settings for cover pages * **#1676**: set page margins correctly via computed header/footer heights for multiple URLs * **#1758**: fix corrupt image when output is specified as "-" in wkhtmltoimage on Windows * **#1722**: **[qt]** fix broken hyphenation with soft-hyphens * **#1769**: fixed unicode URLs in links * **#1772**: added variable 'isodate' for substitution in headers/footers * **#1790**: fix handling of temporary files during PDF conversion via API * **#1808**: fix [sitepage] and [sitepages] not working without HTML headers/footers * **#1825**: fix handling of non-ASCII characters in command-line arguments * **#1863**: **[qt]** blank page or crash with low DPI on Windows * **#1892**: --window-status causes endless loop with --header-html * **#1906**: fix wrong comparison when parsing list parameters * **#1944**: **[breaking change]** fix the reflection subsystem to fix the non-functional API * **#1949**: fix generation of tarball in the posix-local build * **#1955**: installer does not work on 32-bit OS X (10.6.x or 10.7.x) * **#1961**: add explicit dependency on minimal font packages for all linux targets * **#1988**: fix footer spacing being ignored (and header spacing being used instead) * **#1992**: add support for CentOS 7 target * **#2055**: **[qt]** rendering of Thai symbols is very slow v0.12.1 (2014-06-26) -------------------- * removed support for PostScript output which is not supported in QT5 * use OpenSSL 1.0.1h for the Windows builds * **#1502**: fix spurious "exit with code 1 due to http error: 1xxx" errors * **#1504**: **[qt]** fix rendering issues for JPEG with XMP metadata * **#1507**: **[qt]** fix crash when CSS widows are specified * **#1509**: fix TOC support which was broken after upgrade to latest Qt * **#1512**: **[qt]** fix crashes when rendering JPEG images on Windows Server 2008 x64 * **#1544**: use UTF-8 encoding for the HTML generated by the TOC XSL * **#1545**: PDFs rendering without embedded fonts on OS X * **#1546**: fix problem with non-ASCII characters in output path on Windows * **#1585**: delete existing files explicitly in windows installer * **#1586**: **[qt]** suppress blank page generated if the first cell spans multiple pages * **#1631**: **[qt]** crash when hiding header for a specific page * **#1686**: **[qt]** --user-style-sheet does not work on Windows * **#1757**: fix parsing of ColorMode and PrinterMode in the API * **#1764**: include text codecs for Chinese (Simplified/Traditional), Japanese and Korean * fix compilation failures when not building with patched Qt/WebKit * support building with non-patched Qt4/Qt5 in either shared or static mode * implement a --license command line option * update URLs in the internal documentation * generate API documentation for libwkhtmltox (on the website) * display version in compiled binary properly under various scenarios * complete revamp of the build system, which now generates native packages on all platforms v0.12.0 (2014-02-06) -------------------- * **#443**: add "sitepage" and "sitepages" support for headers * **#175**: add ability to auto calculate header/footer heights * **#1086**: don't return freed memory; instead use a string cache * **#648**: delete infinite warnings into console about window status * **#550**: enable tunneling to use a HTTP proxy for HTTPS * **#1277**: avoid crash due to premature deletion of ResourceObject * lots of fixes/enhancements for memory and error management * add *--quiet* option to wkhtmltoimage * add *--cache-dir* option for configuring web cache directory * add *--load-media-error-handling* to handle errors for media files * add *--viewport-size* to specify viewport size * reserve heights when not using HTML header/footer * lots of improvements in the build system * lots of typos were fixed in various places * **[qt]** rebase patch series on QT 4.8.5 (now hosted on github) * **[qt]** fixes to get static builds working for MSVC 2010 (32/64 bit) * **[qt]** prevent page breaks in table rows * **[qt]** repeat THEAD/TFOOT when table contains page breaks * **[qt]** improve font kerning as per Webkit bug 93263 * **[qt]** various table page-break improvements * **[qt]** fix rendering due to incorrect page height computation * **[qt]** implement "page-break-inside: avoid" for non-floating block elements * **[qt]** enable WOFF file support * **[qt]** add support for CSS widows and orphans for block elements wkhtmltopdf-0.12.5/Doxyfile000066400000000000000000001742211343154624600156670ustar00rootroot00000000000000# Doxyfile 1.6.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = "libwkhtmltox" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = libdoc/ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it parses. # With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this tag. # The format is ext=language, where ext is a file extension, and language is one of # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT += src/lib/pdf.h src/lib/pdf_c_bindings.cc INPUT += src/lib/image.h src/lib/image_c_bindings.cc INPUT += src/lib/pdfsettings.hh src/lib/pdfsettings.cc INPUT += src/lib/imagesettings.hh src/lib/imagesettings.cc INPUT += src/lib/doc.cc # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.cc *.inc *.hh *.c *.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = */static-build/* */.git/* */release-* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) # there is already a search function so this one should typically # be disabled. SEARCHENGINE = YES #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = include # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = __EXTENSIVE_WKHTMLTOPDF_QT_HACK__= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES wkhtmltopdf-0.12.5/LICENSE000066400000000000000000000167431343154624600151720ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. wkhtmltopdf-0.12.5/README.md000066400000000000000000000005201343154624600154260ustar00rootroot00000000000000wkhtmltopdf and wkhtmltoimage ----------------------------- wkhtmltopdf and wkhtmltoimage are command line tools to render HTML into PDF and various image formats using the QT Webkit rendering engine. These run entirely "headless" and do not require a display or display service. See http://wkhtmltopdf.org for updated documentation. wkhtmltopdf-0.12.5/VERSION000066400000000000000000000000061343154624600152160ustar00rootroot000000000000000.12.5wkhtmltopdf-0.12.5/appveyor.yml000066400000000000000000000007361343154624600165500ustar00rootroot00000000000000version: "{build}" clone_folder: c:\wkhtmltopdf\wkhtmltopdf test: off environment: matrix: - TARGET: msvc2015-win32 install: - git submodule update --init --recursive --force --depth 50 - git clone https://github.com/wkhtmltopdf/packaging.git ..\packaging - pip install -q conan pyyaml - perl -p -i.bak -e "s/quiet = 0/quiet = 1/g" qt/bin/syncqt build_script: - python ..\packaging\build vagrant --version - - %TARGET% c:\wkhtmltopdf\wkhtmltopdf wkhtmltopdf-0.12.5/common.pri000066400000000000000000000030311343154624600161530ustar00rootroot00000000000000# Copyright 2010, 2011 wkhtmltopdf authors # # This file is part of wkhtmltopdf. # # wkhtmltopdf is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # wkhtmltopdf is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with wkhtmltopdf. If not, see . CONFIG(static, shared|static):lessThan(QT_MAJOR_VERSION, 5) { DEFINES += QT4_STATICPLUGIN_TEXTCODECS QTPLUGIN += qcncodecs qjpcodecs qkrcodecs qtwcodecs } INCLUDEPATH += ../../src/lib RESOURCES = $$PWD/wkhtmltopdf.qrc win32: CONFIG += console win32-g++*: QMAKE_LFLAGS += -static -static-libgcc -static-libstdc++ QT += webkit network xmlpatterns svg greaterThan(QT_MAJOR_VERSION, 4) { QT += webkitwidgets greaterThan(QT_MINOR_VERSION, 2): QT += printsupport } # version related information VERSION_TEXT=$$(WKHTMLTOX_VERSION) isEmpty(VERSION_TEXT): VERSION_TEXT=$$cat($$PWD/VERSION) VERSION_LIST=$$split(VERSION_TEXT, "-") count(VERSION_LIST, 1): VERSION=$$VERSION_TEXT else: VERSION=$$member(VERSION_LIST, 0) DEFINES += VERSION=$$VERSION FULL_VERSION=$$VERSION_TEXT BUILDING_WKHTMLTOX wkhtmltopdf-0.12.5/examples/000077500000000000000000000000001343154624600157705ustar00rootroot00000000000000wkhtmltopdf-0.12.5/examples/Makefile000066400000000000000000000004341343154624600174310ustar00rootroot00000000000000CFLAGS= -I ../include LDFLAGS=-L ../bin -lwkhtmltox -Wall -ansi -pedantic -ggdb EXES=pdf_c_api image_c_api all: $(EXES) .PHONY: clean run all run: pdf_c_api LD_LIBRARY_PATH=../bin ./pdf_c_api runimage: image_c_api LD_LIBRARY_PATH=../bin ./image_c_api clean: $(RM) $(EXES) wkhtmltopdf-0.12.5/examples/image_c_api.c000066400000000000000000000066441343154624600203630ustar00rootroot00000000000000/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- * vi:set ts=4 sts=4 sw=4 noet : * * Copyright 2010, 2011 wkhtmltopdf authors * * This file is part of wkhtmltopdf. * * wkhtmltopdf is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * wkhtmltopdf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with wkhtmltopdf. If not, see . */ /* This is a simple example program showing how to use the wkhtmltopdf c bindings */ #include #include #include /* Print out loading progress information */ void progress_changed(wkhtmltoimage_converter * c, int p) { printf("%3d%%\r",p); fflush(stdout); } /* Print loading phase information */ void phase_changed(wkhtmltoimage_converter * c) { int phase = wkhtmltoimage_current_phase(c); printf("%s\n", wkhtmltoimage_phase_description(c, phase)); } /* Print a message to stderr when an error occurs */ void error(wkhtmltoimage_converter * c, const char * msg) { fprintf(stderr, "Error: %s\n", msg); } /* Print a message to stderr when a warning is issued */ void warning(wkhtmltoimage_converter * c, const char * msg) { fprintf(stderr, "Warning: %s\n", msg); } /* Main method convert image */ int main() { wkhtmltoimage_global_settings * gs; wkhtmltoimage_converter * c; const unsigned char * data; long len; /* Init wkhtmltoimage in graphics less mode */ wkhtmltoimage_init(false); /* * Create a global settings object used to store options that are not * related to input objects, note that control of this object is parsed to * the converter later, which is then responsible for freeing it */ gs = wkhtmltoimage_create_global_settings(); /* We want to convert the qstring documentation page */ wkhtmltoimage_set_global_setting(gs, "in", "http://www.google.com/"); wkhtmltoimage_set_global_setting(gs, "fmt", "jpeg"); /* Create the actual converter object used to convert the pages */ c = wkhtmltoimage_create_converter(gs, NULL); /* Call the progress_changed function when progress changes */ wkhtmltoimage_set_progress_changed_callback(c, progress_changed); /* Call the phase _changed function when the phase changes */ wkhtmltoimage_set_phase_changed_callback(c, phase_changed); /* Call the error function when an error occurs */ wkhtmltoimage_set_error_callback(c, error); /* Call the warning function when a warning is issued */ wkhtmltoimage_set_warning_callback(c, warning); /* Perform the actual conversion */ if (!wkhtmltoimage_convert(c)) fprintf(stderr, "Conversion failed!"); /* Output possible http error code encountered */ printf("httpErrorCode: %d\n", wkhtmltoimage_http_error_code(c)); len = wkhtmltoimage_get_output(c, &data); printf("%ld len\n", len); /* Destroy the converter object since we are done with it */ wkhtmltoimage_destroy_converter(c); /* We will no longer be needing wkhtmltoimage funcionality */ wkhtmltoimage_deinit(); return 0; } wkhtmltopdf-0.12.5/examples/pdf_c_api.c000066400000000000000000000076651343154624600200560ustar00rootroot00000000000000/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- * vi:set ts=4 sts=4 sw=4 noet : * * Copyright 2010, 2011 wkhtmltopdf authors * * This file is part of wkhtmltopdf. * * wkhtmltopdf is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * wkhtmltopdf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with wkhtmltopdf. If not, see . */ /* This is a simple example program showing how to use the wkhtmltopdf c bindings */ #include #include #include /* Print out loading progress information */ void progress_changed(wkhtmltopdf_converter * c, int p) { printf("%3d%%\r",p); fflush(stdout); } /* Print loading phase information */ void phase_changed(wkhtmltopdf_converter * c) { int phase = wkhtmltopdf_current_phase(c); printf("%s\n", wkhtmltopdf_phase_description(c, phase)); } /* Print a message to stderr when an error occurs */ void error(wkhtmltopdf_converter * c, const char * msg) { fprintf(stderr, "Error: %s\n", msg); } /* Print a message to stderr when a warning is issued */ void warning(wkhtmltopdf_converter * c, const char * msg) { fprintf(stderr, "Warning: %s\n", msg); } /* Main method convert pdf */ int main() { wkhtmltopdf_global_settings * gs; wkhtmltopdf_object_settings * os; wkhtmltopdf_converter * c; /* Init wkhtmltopdf in graphics less mode */ wkhtmltopdf_init(false); /* * Create a global settings object used to store options that are not * related to input objects, note that control of this object is parsed to * the converter later, which is then responsible for freeing it */ gs = wkhtmltopdf_create_global_settings(); /* We want the result to be storred in the file called test.pdf */ wkhtmltopdf_set_global_setting(gs, "out", "test.pdf"); wkhtmltopdf_set_global_setting(gs, "load.cookieJar", "myjar.jar"); /* * Create a input object settings object that is used to store settings * related to a input object, note again that control of this object is parsed to * the converter later, which is then responsible for freeing it */ os = wkhtmltopdf_create_object_settings(); /* We want to convert to convert the qstring documentation page */ wkhtmltopdf_set_object_setting(os, "page", "http://doc.qt.io/qt-5/qstring.html"); /* Create the actual converter object used to convert the pages */ c = wkhtmltopdf_create_converter(gs); /* Call the progress_changed function when progress changes */ wkhtmltopdf_set_progress_changed_callback(c, progress_changed); /* Call the phase _changed function when the phase changes */ wkhtmltopdf_set_phase_changed_callback(c, phase_changed); /* Call the error function when an error occurs */ wkhtmltopdf_set_error_callback(c, error); /* Call the warning function when a warning is issued */ wkhtmltopdf_set_warning_callback(c, warning); /* * Add the the settings object describing the qstring documentation page * to the list of pages to convert. Objects are converted in the order in which * they are added */ wkhtmltopdf_add_object(c, os, NULL); /* Perform the actual conversion */ if (!wkhtmltopdf_convert(c)) fprintf(stderr, "Conversion failed!"); /* Output possible http error code encountered */ printf("httpErrorCode: %d\n", wkhtmltopdf_http_error_code(c)); /* Destroy the converter object since we are done with it */ wkhtmltopdf_destroy_converter(c); /* We will no longer be needing wkhtmltopdf funcionality */ wkhtmltopdf_deinit(); return 0; } wkhtmltopdf-0.12.5/src/000077500000000000000000000000001343154624600147415ustar00rootroot00000000000000wkhtmltopdf-0.12.5/src/image/000077500000000000000000000000001343154624600160235ustar00rootroot00000000000000wkhtmltopdf-0.12.5/src/image/image.pro000066400000000000000000000026331343154624600176330ustar00rootroot00000000000000# Copyright 2010, 2011 wkhtmltopdf authors # # This file is part of wkhtmltopdf. # # wkhtmltopdf is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # wkhtmltopdf is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with wkhtmltopdf. If not, see . include(../../common.pri) TEMPLATE = app TARGET = wkhtmltoimage DESTDIR = ../../bin DEPENDPATH += . ../shared INCLUDEPATH += . ../shared unix { man.path=$$INSTALLBASE/share/man/man1 man.extra=LD_LIBRARY_PATH=../../bin/ ../../bin/wkhtmltoimage --manpage | gzip > $(INSTALL_ROOT)$$INSTALLBASE/share/man/man1/wkhtmltoimage.1.gz QMAKE_EXTRA_TARGETS += man INSTALLS += man } macx { CONFIG -= app_bundle } INSTALLS += target target.path=$$INSTALLBASE/bin include(../shared/shared.pri) CONFIG(shared, shared|static) { LIBS += -L../../bin -lwkhtmltox } else { include(../lib/lib.pri) } # Input SOURCES += wkhtmltoimage.cc imagearguments.cc imagecommandlineparser.cc imagedocparts.cc wkhtmltopdf-0.12.5/src/image/imagearguments.cc000066400000000000000000000061321343154624600213440ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "arghandler.inl" #include "imagecommandlineparser.hh" #include ImageCommandLineParser::ImageCommandLineParser(wkhtmltopdf::settings::ImageGlobal & s): settings(s) { mode(global); section("General Options"); addDocArgs(); addWebArgs(s.web); extended(false); qthack(false); addarg("quiet", 'q', "Be less verbose, maintained for backwards compatibility; Same as using --log-level none", new ConstSetter(s.logLevel, wkhtmltopdf::settings::None)); addarg("log-level", 0, "Set log level to: none, error, warn or info", new LogLevelSetter(s.logLevel, "level")); addarg("width",0,"Set screen width, note that this is used only as a guide line. Use --disable-smart-width to make it strict.", new IntSetter(s.screenWidth,"int")); addarg("height",0,"Set screen height (default is calculated from page content)", new IntSetter(s.screenHeight, "int")); // addarg("scale-w",0,"Set width for resizing", new IntSetter(s.scale.width,"int")); // addarg("scale-h",0,"Set height for resizing", new IntSetter(s.scale.height,"int")); addarg("crop-x",0,"Set x coordinate for cropping", new IntSetter(s.crop.left,"int")); addarg("crop-y",0,"Set y coordinate for cropping", new IntSetter(s.crop.top,"int")); addarg("crop-w",0,"Set width for cropping", new IntSetter(s.crop.width,"int")); addarg("crop-h",0,"Set height for cropping", new IntSetter(s.crop.height,"int")); addarg("format",'f',"Output file format", new QStrSetter(s.fmt, "format") ); addarg("quality",0,"Output image quality (between 0 and 100)", new IntSetter(s.quality, "int") ); extended(true); qthack(true); addarg("disable-smart-width", 0, "Use the specified width even if it is not large enough for the content", new ConstSetter(s.smartWidth, false)); addarg("enable-smart-width", 0, "Extend --width to fit unbreakable content", new ConstSetter(s.smartWidth, true)); addarg("transparent",0,"Make the background transparent in pngs", new ConstSetter(s.transparent, true)); #ifdef Q_OS_UNIX addarg("use-xserver",0,"Use the X server (some plugins and other stuff might not work without X11)", new ConstSetter(s.useGraphics,true)); #endif addGlobalLoadArgs(s.loadGlobal); addPageLoadArgs(s.loadPage); } wkhtmltopdf-0.12.5/src/image/imagecommandlineparser.cc000066400000000000000000000075571343154624600230560ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "imagecommandlineparser.hh" #include "outputter.hh" #include /*! \file commandlineparser.hh \brief Defines the ImageCommandLineParser class */ /*! Output the man page to a given file \param fd The file to store the man page */ void ImageCommandLineParser::manpage(FILE * fd) const { Outputter * o = Outputter::man(fd); outputManName(o); outputSynopsis(o); outputDescripton(o); outputSwitches(o, true, false); outputContact(o); outputAuthors(o); delete o; } /*! Output usage information aka. --help \param fd The file to output the information to \param extended Should we show extended arguments */ void ImageCommandLineParser::usage(FILE * fd, bool extended) const { Outputter * o = Outputter::text(fd,false); outputName(o); outputSynopsis(o); outputDescripton(o); outputSwitches(o, extended, false); if (extended) { outputProxyDoc(o); } outputContact(o); delete o; } /*! Output the readme/manual \param fd The file to output to \param html Do we want the html manaul, or the README */ void ImageCommandLineParser::readme(FILE * fd, bool html) const { Outputter * o = html?Outputter::html(fd):Outputter::text(fd, true); outputDocStart(o); outputContact(o); outputLicense(o); outputAuthors(o); outputSynopsis(o); outputSwitches(o, true, true); outputProxyDoc(o); outputStaticProblems(o); outputCompilation(o); outputInstallation(o); outputExamples(o); delete o; } /*! * Load default arguments and put them in the settings structure */ // void ImageCommandLineParser::loadDefaults() { // d->settings.in = "-"; // d->settings.proxy.host = ""; // foreach (ArgHandler * h, d->longToHandler) // h->useDefault(*d); // //Load configuration from environment // char * val; // const char * vars[] = {"proxy","all_proxy","http_proxy", NULL}; // for (int i=0; vars[i]; ++i) { // if ((val = getenv("proxy"))) { // bool ok=false; // Settings::ProxySettings p = Settings::strToProxy(val, &ok); // if (ok) // d->settings.proxy = p; // } // } // } /*! * Parse command line arguments, and set settings accordingly. * \param argc the number of command line arguments * \param argv a NULL terminated list with the arguments */ void ImageCommandLineParser::parseArguments(int argc, const char ** argv, bool final) { settings.in=""; settings.out=""; bool defaultMode=false; for (int i=1; i < argc; ++i) { if (i==argc-2 && (argv[i][0] != '-' || argv[i][1] == '\0')) { // the arg before last (in) settings.in = QString::fromLocal8Bit(argv[i]); } else if (i==argc-1 && (argv[i][0] != '-' || argv[i][1] == '\0')) { // the last arg (out) settings.out = QString::fromLocal8Bit(argv[i]); } else { parseArg(global, argc, argv, defaultMode, i, 0); } } if (final || settings.in=="" || settings.out=="") { fprintf(stderr, "You need to specify at least one input file, and exactly one output file\nUse - for stdin or stdout\n\n"); usage(stderr, false); exit(1); } } wkhtmltopdf-0.12.5/src/image/imagecommandlineparser.hh000066400000000000000000000043661343154624600230630ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __IMAGECOMMANDLINEPARSER_HH__ #define __IMAGECOMMANDLINEPARSER_HH__ #include "commandlineparserbase.hh" #include #include /*! \brief The class is responsible for parsing command line information */ class ImageCommandLineParser: public CommandLineParserBase { public: const static int global = 1; wkhtmltopdf::settings::ImageGlobal & settings; //arguments.cc ImageCommandLineParser(wkhtmltopdf::settings::ImageGlobal & settings); ~ImageCommandLineParser() {}; //docparts.cc void outputManName(Outputter * o) const; void outputSynopsis(Outputter * o) const; void outputDescripton(Outputter * o) const; void outputArgsFromStdin(Outputter * o) const; void outputNotPatched(Outputter * o, bool sure) const; void outputPageBreakDoc(Outputter * o) const; void outputContact(Outputter * o) const; void outputDocStart(Outputter * o) const; void outputCompilation(Outputter * o) const; void outputInstallation(Outputter * o) const; void outputExamples(Outputter * o) const; //commandlineparser.cc virtual void usage(FILE * fd, bool extended) const; virtual void manpage(FILE * fd) const; virtual void readme(FILE * fd, bool html) const; virtual QString appName() const {return "wkhtmltoimage";} //void loadDefaults(); void parseArguments(int argc, const char ** argv, bool final=false); }; #endif //__IMAGECOMMANDLINEPARSER_HH__ wkhtmltopdf-0.12.5/src/image/imagedocparts.cc000066400000000000000000000075731343154624600211700ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "imagecommandlineparser.hh" #include "outputter.hh" #include #define STRINGIZE_(x) #x #define STRINGIZE(x) STRINGIZE_(x) /*! Output name and a short description \param o The outputter to output to */ void ImageCommandLineParser::outputManName(Outputter * o) const { o->beginSection("Name"); o->paragraph("wkhtmltoimage - html to image converter"); o->endSection(); } /*! Output a short synopsis on how to call the command line program \param o The outputter to output to */ void ImageCommandLineParser::outputSynopsis(Outputter * o) const { o->beginSection("Synopsis"); o->verbatim("wkhtmltoimage [OPTIONS]... \n"); o->endSection(); } /*! Explain what the program does \param o The outputter to output to */ void ImageCommandLineParser::outputDescripton(Outputter * o) const { o->beginSection("Description"); o->beginParagraph(); o->text("Converts an HTML page into an image, "); o->endParagraph(); o->endSection(); } /*! Output contact information \param o The outputter to output to */ void ImageCommandLineParser::outputContact(Outputter * o) const { o->beginSection("Contact"); o->beginParagraph(); o->text("If you experience bugs or want to request new features please visit "); o->link("https://github.com/wkhtmltopdf/wkhtmltopdf/issues"); o->endParagraph(); o->endSection(); } /*! Output beginning of the readme \param o The outputter to output to */ void ImageCommandLineParser::outputDocStart(Outputter * o) const { o->beginSection("wkhtmltoimage " STRINGIZE(FULL_VERSION) " Manual"); o->paragraph("This file documents wkhtmltoimage, a program capable of converting HTML " "documents into images."); o->endSection(); } /*! Output information on how to compile \param o The outputter to output to */ void ImageCommandLineParser::outputCompilation(Outputter * o) const { o->beginSection("Compilation"); o->paragraph("It can happen that the static binary does not work for your system " "for one reason or the other, in that case you might need to compile " "wkhtmltoimage yourself."); o->endParagraph(); o->endSection(); } /*! Output information on how to install \param o The outputter to output to */ void ImageCommandLineParser::outputInstallation(Outputter * o) const { o->beginSection("Installation"); o->paragraph( "There are several ways to install wkhtmltoimage. You can download a " "already compiled binary, or you can compile wkhtmltoimage yourself. "); o->endSection(); } /*! Output examples on how to use wkhtmltoimage \param o The outputter to output to */ void ImageCommandLineParser::outputExamples(Outputter * o) const { o->beginSection("Examples"); o->paragraph("This section presents a number of examples of how to invoke wkhtmltoimage."); o->paragraph("To convert a remote HTML file to PNG:"); o->verbatim("wkhtmltoimage http://www.google.com google.png\n"); o->paragraph("To convert a local HTML file to PNG:"); o->verbatim("wkhtmltoimage my.html my.png\n"); o->endSection(); } wkhtmltopdf-0.12.5/src/image/wkhtmltoimage.cc000066400000000000000000000053151343154624600212120ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "imagecommandlineparser.hh" #include "progressfeedback.hh" #include #include #include #include #include #if defined(Q_OS_UNIX) #include #endif int main(int argc, char** argv) { #if defined(Q_OS_UNIX) setlocale(LC_ALL, ""); #if QT_VERSION >= 0x050000 && !defined(__EXTENSIVE_WKHTMLTOPDF_QT_HACK__) setenv("QT_QPA_PLATFORM", "offscreen", 0); #endif #endif //This will store all our settings wkhtmltopdf::settings::ImageGlobal settings; //Create a command line parser to parse commandline arguments ImageCommandLineParser parser(settings); //Parse the arguments parser.parseArguments(argc, (const char**)argv); bool use_graphics=true; #if defined(Q_OS_UNIX) || defined(Q_OS_MAC) #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ use_graphics=settings.useGraphics; if (!use_graphics) QApplication::setGraphicsSystem("raster"); #endif #endif QApplication a(argc, argv, use_graphics); MyLooksStyle * style = new MyLooksStyle(); a.setStyle(style); //Create the actual page converter to convert the pages wkhtmltopdf::ImageConverter converter(settings); QObject::connect(&converter, SIGNAL(checkboxSvgChanged(const QString &)), style, SLOT(setCheckboxSvg(const QString &))); QObject::connect(&converter, SIGNAL(checkboxCheckedSvgChanged(const QString &)), style, SLOT(setCheckboxCheckedSvg(const QString &))); QObject::connect(&converter, SIGNAL(radiobuttonSvgChanged(const QString &)), style, SLOT(setRadioButtonSvg(const QString &))); QObject::connect(&converter, SIGNAL(radiobuttonCheckedSvgChanged(const QString &)), style, SLOT(setRadioButtonCheckedSvg(const QString &))); wkhtmltopdf::ProgressFeedback feedback(settings.logLevel, converter); bool success = converter.convert(); return handleError(success, converter.httpErrorCode()); } wkhtmltopdf-0.12.5/src/lib/000077500000000000000000000000001343154624600155075ustar00rootroot00000000000000wkhtmltopdf-0.12.5/src/lib/converter.cc000066400000000000000000000113621343154624600200300ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "converter_p.hh" #include "multipageloader.hh" #include #include #ifdef QT4_STATICPLUGIN_TEXTCODECS #include Q_IMPORT_PLUGIN(qcncodecs) Q_IMPORT_PLUGIN(qjpcodecs) Q_IMPORT_PLUGIN(qkrcodecs) Q_IMPORT_PLUGIN(qtwcodecs) #endif namespace wkhtmltopdf { void ConverterPrivate::updateWebSettings(QWebSettings * ws, const settings::Web & s) const { #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ if (!s.defaultEncoding.isEmpty()) ws->setDefaultTextEncoding(s.defaultEncoding); if (!s.enableIntelligentShrinking) { ws->setPrintingMaximumShrinkFactor(1.0); ws->setPrintingMinimumShrinkFactor(1.0); } ws->setPrintingMediaType(s.printMediaType?"print":"screen"); #endif ws->setAttribute(QWebSettings::JavaEnabled, s.enablePlugins); ws->setAttribute(QWebSettings::JavascriptEnabled, s.enableJavascript); ws->setAttribute(QWebSettings::JavascriptCanOpenWindows, false); ws->setAttribute(QWebSettings::JavascriptCanAccessClipboard, false); ws->setFontSize(QWebSettings::MinimumFontSize, s.minimumFontSize); //Newer versions of QT have even more settings to change ws->setAttribute(QWebSettings::PrintElementBackgrounds, s.background); ws->setAttribute(QWebSettings::AutoLoadImages, s.loadImages); ws->setAttribute(QWebSettings::PluginsEnabled, s.enablePlugins); if (!s.userStyleSheet.isEmpty()) ws->setUserStyleSheetUrl(MultiPageLoader::guessUrlFromString(s.userStyleSheet)); } void ConverterPrivate::fail() { error = true; conversionDone = true; clearResources(); emit outer().finished(false); qApp->exit(0); // quit qt's event handling } /*! * Called when the page is loading, display some progress to the using * \param progress the loading progress in percent */ void ConverterPrivate::loadProgress(int progress) { progressString = QString::number(progress) + "%"; emit outer().progressChanged(progress); } void ConverterPrivate::forwardError(QString error) { emit outer().error(error); } void ConverterPrivate::forwardWarning(QString warning) { emit outer().warning(warning); } void ConverterPrivate::cancel() { error=true; } bool ConverterPrivate::convert() { conversionDone=false; beginConvert(); while (!conversionDone) qApp->processEvents(QEventLoop::WaitForMoreEvents | QEventLoop::AllEvents); return !error; } /*! \brief Count the number of phases that the conversion process goes though */ int Converter::phaseCount() { return priv().phaseDescriptions.size(); } /*! \brief return the current phase of conversion */ int Converter::currentPhase() { return priv().currentPhase; } /*! \brief return a textual description of some phase \param phase the phase to get a description of, -1 for current phase */ QString Converter::phaseDescription(int phase) { if (phase < 0 || priv().phaseDescriptions.size() <= phase) phase=priv().currentPhase; if (phase < 0 || priv().phaseDescriptions.size() <= phase) return "Invalid"; return priv().phaseDescriptions[phase]; } /*! \brief return a textual description of progress in the current phase */ QString Converter::progressString() { return priv().progressString; } /*! \brief return the HTTP return code, of the converted page */ int Converter::httpErrorCode() { return priv().errorCode; } /*! \brief Start a asynchronous conversion of html pages to a pdf document. Once conversion is done an finished signal will be emitted */ void Converter::beginConversion() { priv().beginConvert(); } /*! \brief Synchronous convert html pages to a pdf document. */ bool Converter::convert() { return priv().convert(); } /*! \brief Cancel a running conversion */ void Converter::cancel() { priv().cancel(); } void Converter::emitCheckboxSvgs(const settings::LoadPage & ls) { emit checkboxSvgChanged(ls.checkboxSvg); emit checkboxCheckedSvgChanged(ls.checkboxCheckedSvg); emit radiobuttonSvgChanged(ls.radiobuttonSvg); emit radiobuttonCheckedSvgChanged(ls.radiobuttonCheckedSvg); } } wkhtmltopdf-0.12.5/src/lib/converter.hh000066400000000000000000000037061343154624600200450ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __CONVERTER_HH__ #define __CONVERTER_HH__ #include #include #include namespace wkhtmltopdf { class DLL_LOCAL ConverterPrivate; class DLL_PUBLIC Converter: public QObject { Q_OBJECT public: virtual ~Converter() {}; int currentPhase(); int phaseCount(); QString phaseDescription(int phase=-1); QString progressString(); int httpErrorCode(); signals: void warning(const QString & message); void error(const QString & message); void phaseChanged(); void progressChanged(int progress); void finished(bool ok); void checkboxSvgChanged(const QString & path); void checkboxCheckedSvgChanged(const QString & path); void radiobuttonSvgChanged(const QString & path); void radiobuttonCheckedSvgChanged(const QString & path); public slots: void beginConversion(); bool convert(); void cancel(); protected: void emitCheckboxSvgs(const settings::LoadPage & ls); virtual ConverterPrivate & priv() = 0; friend class ConverterPrivate; }; } #include #endif //__CONVERTER_HH__ wkhtmltopdf-0.12.5/src/lib/converter_p.hh000066400000000000000000000034051343154624600203600ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __CONVERTER_P_HH__ #define __CONVERTER_P_HH__ #include "converter.hh" #include "websettings.hh" #include #include #include "dllbegin.inc" namespace wkhtmltopdf { class DLL_LOCAL ConverterPrivate: public QObject { Q_OBJECT public: void copyFile(QFile & src, QFile & dst); QList phaseDescriptions; int currentPhase; QString progressString; protected: bool error; virtual void clearResources() = 0; virtual Converter & outer() = 0; int errorCode; bool conversionDone; void updateWebSettings(QWebSettings * ws, const settings::Web & s) const; public slots: void fail(); void loadProgress(int progress); virtual void beginConvert() = 0; void cancel(); bool convert(); void forwardError(QString error); void forwardWarning(QString warning); private: friend class Converter; }; } #include "dllend.inc" #endif //__CONVERTER_P_HH__ wkhtmltopdf-0.12.5/src/lib/dllbegin.inc000066400000000000000000000031451343154624600177650ustar00rootroot00000000000000/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- * vi:set ts=4 sts=4 sw=4 noet : * * Copyright 2010 wkhtmltopdf authors * * This file is part of wkhtmltopdf. * * wkhtmltopdf is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * wkhtmltopdf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with wkhtmltopdf. If not, see . */ #ifndef __WKHTMLTOPDF_DLLBEGIN__ #define __WKHTMLTOPDF_DLLBEGIN__ #if defined _WIN32 || defined __CYGWIN__ #ifdef BUILDING_DLL #define DLL_PUBLIC __declspec(dllexport) #else #define DLL_PUBLIC __declspec(dllimport) #endif #define DLL_LOCAL #else #if __GNUC__ >= 4 #define DLL_PUBLIC __attribute__ ((visibility("default"))) #define DLL_LOCAL __attribute__ ((visibility("hidden"))) #else #define DLL_PUBLIC #define DLL_LOCAL #endif #endif #if defined _WIN32 #define CALLTYPE __stdcall #else #define CALLTYPE #endif #ifdef __cplusplus #define CAPI(type) extern "C" DLL_PUBLIC type CALLTYPE #else #define CAPI(type) DLL_PUBLIC type CALLTYPE #endif #endif /*__WKHTMLTOPDF_DLLBEGIN__*/ wkhtmltopdf-0.12.5/src/lib/dllend.inc000066400000000000000000000020611343154624600174430ustar00rootroot00000000000000/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- * vi:set ts=4 sts=4 sw=4 noet : * * Copyright 2010 wkhtmltopdf authors * * This file is part of wkhtmltopdf. * * wkhtmltopdf is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * wkhtmltopdf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with wkhtmltopdf. If not, see . */ #ifdef __WKHTMLTOPDF_DLLBEGIN__ #undef __WKHTMLTOPDF_DLLBEGIN__ #undef DLL_PUBLIC #undef DLL_LOCAL #undef CAPI #undef CALLTYPE #endif /*__WKHTMLTOPDF_DLLBEGIN__*/ wkhtmltopdf-0.12.5/src/lib/doc.cc000066400000000000000000000075601343154624600165730ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . /** * \mainpage * * libwkhtmltox is divided into several parts. * * \section PDFH To PDF c-bindings * * The file \ref pdf.h contains a * fairly high level and stable pure c binding to wkhtmltopdf. These * binding are well documented and do not depend on QT. Using this is * the recommended way of interfacing with the PDF portion of * libwkhtmltox. * * Using these binding it is relatively straight forward to convert one * or more HTML document to a PDF file, using the following process: * * - \ref wkhtmltopdf_init is called. * - A \ref wkhtmltopdf_global_settings object is creating by calling * \ref wkhtmltopdf_create_global_settings. * - Non web page specific \ref pagesettings for the conversion are set by multiple * calls to \ref wkhtmltopdf_set_global_setting. * - A \ref wkhtmltopdf_converter object is created by calling * \ref wkhtmltopdf_create_converter, which consumes the global_settings instance. * - A number of object (web pages) are added to the conversion process, this is done by * - Creating a \ref wkhtmltopdf_object_settings instance by calling * \ref wkhtmltopdf_create_object_settings. * - Setting web page specific \ref pagesettings by multiple calls to * \ref wkhtmltopdf_set_object_setting. * - Adding the object to the conversion process by calling \ref wkhtmltopdf_add_object * - A number of callback function are added to the converter object. * - The conversion is performed by calling \ref wkhtmltopdf_convert. * - The converter object is destroyed by calling \ref wkhtmltopdf_destroy_converter. * * \section IMAGEH To image c-bindings * * The file \ref image.h contains a * fairly high level and stable pure c binding to wkhtmltoimage. These * binding are well documented and do not depend on QT. Using this is * the recommended way of interfacing with the image portion of * libwkhtmltox. * * Using these binding it is relatively straight forward to convert one * or more HTML document to a raster image or SVG document, using the following process: * * - \ref wkhtmltoimage_init is called. * - A \ref wkhtmltoimage_global_settings object is creating by calling * \ref wkhtmltoimage_create_global_settings. * - \ref pagesettings for the conversion are set by multiple * calls to \ref wkhtmltoimage_set_global_setting. * - A \ref wkhtmltoimage_converter object is created by calling * \ref wkhtmltoimage_create_converter, which consumes the global_settings instance. * - A number of callback function are added to the converter object. * - The conversion is performed by calling \ref wkhtmltoimage_convert. * - The converter object is destroyed by calling \ref wkhtmltoimage_destroy_converter. * * \section RESTH The rest of the headers. * * The rest of the headers directly exposes the C++ QT dependent class * used internally by wkhtmltopdf and wkhtmltoimage. They are not * fairly well documented and are not guaranteed to remain stable. * unless you know what you are doing you should not use these bindings. * */ wkhtmltopdf-0.12.5/src/lib/image.h000066400000000000000000000071571343154624600167540ustar00rootroot00000000000000/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- * vi:set ts=4 sts=4 sw=4 noet : * * Copyright 2010 wkhtmltopdf authors * * This file is part of wkhtmltopdf. * * wkhtmltopdf is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * wkhtmltopdf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with wkhtmltopdf. If not, see . */ #ifndef __IMAGE_H__ #define __IMAGE_H__ #ifdef BUILDING_WKHTMLTOX #include "dllbegin.inc" #else #include #endif struct wkhtmltoimage_global_settings; typedef struct wkhtmltoimage_global_settings wkhtmltoimage_global_settings; struct wkhtmltoimage_converter; typedef struct wkhtmltoimage_converter wkhtmltoimage_converter; typedef void (*wkhtmltoimage_str_callback)(wkhtmltoimage_converter * converter, const char * str); typedef void (*wkhtmltoimage_int_callback)(wkhtmltoimage_converter * converter, const int val); typedef void (*wkhtmltoimage_void_callback)(wkhtmltoimage_converter * converter); CAPI(int) wkhtmltoimage_init(int use_graphics); CAPI(int) wkhtmltoimage_deinit(); CAPI(int) wkhtmltoimage_extended_qt(); CAPI(const char *)wkhtmltoimage_version(); CAPI(wkhtmltoimage_global_settings *) wkhtmltoimage_create_global_settings(); CAPI(int) wkhtmltoimage_set_global_setting(wkhtmltoimage_global_settings * settings, const char * name, const char * value); CAPI(int) wkhtmltoimage_get_global_setting(wkhtmltoimage_global_settings * settings, const char * name, char * value, int vs); CAPI(wkhtmltoimage_converter *) wkhtmltoimage_create_converter(wkhtmltoimage_global_settings * settings, const char * data); CAPI(void) wkhtmltoimage_destroy_converter(wkhtmltoimage_converter * converter); CAPI(void) wkhtmltoimage_set_warning_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_str_callback cb); CAPI(void) wkhtmltoimage_set_error_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_str_callback cb); CAPI(void) wkhtmltoimage_set_phase_changed_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_void_callback cb); CAPI(void) wkhtmltoimage_set_progress_changed_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_int_callback cb); CAPI(void) wkhtmltoimage_set_finished_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_int_callback cb); CAPI(int) wkhtmltoimage_convert(wkhtmltoimage_converter * converter); /* CAPI(void) wkhtmltoimage_begin_conversion(wkhtmltoimage_converter * converter); */ /* CAPI(void) wkhtmltoimage_cancel(wkhtmltoimage_converter * converter); */ CAPI(int) wkhtmltoimage_current_phase(wkhtmltoimage_converter * converter); CAPI(int) wkhtmltoimage_phase_count(wkhtmltoimage_converter * converter); CAPI(const char *) wkhtmltoimage_phase_description(wkhtmltoimage_converter * converter, int phase); CAPI(const char *) wkhtmltoimage_progress_string(wkhtmltoimage_converter * converter); CAPI(int) wkhtmltoimage_http_error_code(wkhtmltoimage_converter * converter); CAPI(long) wkhtmltoimage_get_output(wkhtmltoimage_converter * converter, const unsigned char **); #ifdef BUILDING_WKHTMLTOX #include "dllend.inc" #else #include #endif #endif /*__IMAGE_H__*/ wkhtmltopdf-0.12.5/src/lib/image_c_bindings.cc000066400000000000000000000177231343154624600212710ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . /** * \page pagesettings Setting * \section pageImageGlobal Image settings * The \ref wkhtmltoimage_global_settings structure contains the following settings: * - \b crop.left left/x coordinate of the window to capture in pixels. E.g. "200" * - \b crop.top top/y coordinate of the window to capture in pixels. E.g. "200" * - \b crop.width Width of the window to capture in pixels. E.g. "200" * - \b crop.height Height of the window to capture in pixels. E.g. "200" * - \b load.cookieJar Path of file used to load and store cookies. * - \b load.* Page specific settings related to loading content, see \ref pageLoad. * - \b web.* See \ref pageWeb. * - \b transparent When outputting a PNG or SVG, make the white background transparent. * Must be either "true" or "false" * - \b in The URL or path of the input file, if "-" stdin is used. E.g. "http://google.com" * - \b out The path of the output file, if "-" stdout is used, if empty the content is stored * to a internalBuffer. * - \b fmt The output format to use, must be either "", "jpg", "png", "bmp" or "svg". * - \b screenWidth The with of the screen used to render is pixels, e.g "800". * - \b smartWidth Should we expand the screenWidth if the content does not fit? * must be either "true" or "false". * - \b quality The compression factor to use when outputting a JPEG image. E.g. "94". */ #include "image_c_bindings_p.hh" #include "pdf.h" #include "dllbegin.inc" using namespace wkhtmltopdf; void MyImageConverter::warning(const QString & message) { if (warning_cb && globalSettings->logLevel > settings::Error) (warning_cb)(reinterpret_cast(this), message.toUtf8().constData()); } void MyImageConverter::error(const QString & message) { if (error_cb && globalSettings->logLevel > settings::None) (error_cb)(reinterpret_cast(this), message.toUtf8().constData()); } void MyImageConverter::phaseChanged() { if (phase_changed) (phase_changed)(reinterpret_cast(this)); } void MyImageConverter::progressChanged(int progress) { if (progress_changed) (progress_changed)(reinterpret_cast(this), progress); } void MyImageConverter::finished(bool ok) { if (finished_cb) (finished_cb)(reinterpret_cast(this), ok); } MyImageConverter::MyImageConverter(settings::ImageGlobal * gs, const QString * data): warning_cb(0), error_cb(0), phase_changed(0), progress_changed(0), finished_cb(0), converter(*gs, data), globalSettings(gs) { connect(&converter, SIGNAL(warning(const QString &)), this, SLOT(warning(const QString &))); connect(&converter, SIGNAL(error(const QString &)), this, SLOT(error(const QString &))); connect(&converter, SIGNAL(phaseChanged()), this, SLOT(phaseChanged())); connect(&converter, SIGNAL(progressChanged(int)), this, SLOT(progressChanged(int))); connect(&converter, SIGNAL(finished(bool)), this, SLOT(finished(bool))); } MyImageConverter::~MyImageConverter() { delete globalSettings; } CAPI(int) wkhtmltoimage_extended_qt() { return wkhtmltopdf_extended_qt(); } CAPI(const char *) wkhtmltoimage_version() { return "NOT IMPLEMENTED"; } CAPI(int) wkhtmltoimage_init(int use_graphics) { return wkhtmltopdf_init(use_graphics); } CAPI(int) wkhtmltoimage_deinit() { return wkhtmltopdf_deinit(); } CAPI(wkhtmltoimage_global_settings *) wkhtmltoimage_create_global_settings() { return reinterpret_cast(new settings::ImageGlobal()); } CAPI(void) wkhtmltoimage_destroy_global_settings(wkhtmltoimage_global_settings * obj) { delete reinterpret_cast(obj); } CAPI(int) wkhtmltoimage_set_global_setting(wkhtmltoimage_global_settings * settings, const char * name, const char * value) { return reinterpret_cast(settings)->set(name, QString::fromUtf8(value)); } CAPI(int) wkhtmltoimage_get_global_setting(wkhtmltoimage_global_settings * settings, const char * name, char * value, int vs) { QString res = reinterpret_cast(settings)->get(name); if (res.isNull()) return 0; qstrncpy(value, res.toUtf8().constData(), vs); return 1; } CAPI(wkhtmltoimage_converter *) wkhtmltoimage_create_converter(wkhtmltoimage_global_settings * settings, const char * data) { QString str= QString::fromUtf8(data); return reinterpret_cast( new MyImageConverter(reinterpret_cast(settings), &str)); } CAPI(void) wkhtmltoimage_destroy_converter(wkhtmltoimage_converter * converter) { delete reinterpret_cast(converter); } CAPI(void) wkhtmltoimage_set_warning_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_str_callback cb) { reinterpret_cast(converter)->warning_cb = cb; } CAPI(void) wkhtmltoimage_set_error_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_str_callback cb) { reinterpret_cast(converter)->error_cb = cb; } CAPI(void) wkhtmltoimage_set_phase_changed_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_void_callback cb) { reinterpret_cast(converter)->phase_changed = cb; } CAPI(void) wkhtmltoimage_set_progress_changed_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_int_callback cb) { reinterpret_cast(converter)->progress_changed = cb; } CAPI(void) wkhtmltoimage_set_finished_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_int_callback cb) { reinterpret_cast(converter)->finished_cb = cb; } /*CAPI(void) wkhtmltoimage_begin_conversion(wkhtmltoimage_converter * converter) { reinterpret_cast(converter)->converter.beginConversion(); }*/ CAPI(int) wkhtmltoimage_convert(wkhtmltoimage_converter * converter) { return reinterpret_cast(converter)->converter.convert(); } /*CAPI(void) wkhtmltoimage_cancel(wkhtmltoimage_converter * converter) { reinterpret_cast(converter)->converter.cancel(); }*/ CAPI(int) wkhtmltoimage_current_phase(wkhtmltoimage_converter * converter) { return reinterpret_cast(converter)->converter.currentPhase(); } CAPI(int) wkhtmltoimage_phase_count(wkhtmltoimage_converter * converter) { return reinterpret_cast(converter)->converter.phaseCount(); } CAPI(const char *) wkhtmltoimage_phase_description(wkhtmltoimage_converter * converter, int phase) { return reinterpret_cast(converter)->converter.phaseDescription(phase).toUtf8().constData(); } CAPI(const char *) wkhtmltoimage_progress_string(wkhtmltoimage_converter * converter) { return reinterpret_cast(converter)->converter.progressString().toUtf8().constData(); } CAPI(int) wkhtmltoimage_http_error_code(wkhtmltoimage_converter * converter) { return reinterpret_cast(converter)->converter.httpErrorCode(); } CAPI(long) wkhtmltoimage_get_output(wkhtmltoimage_converter * converter, const unsigned char ** d) { const QByteArray & out = reinterpret_cast(converter)->converter.output(); *d = (const unsigned char*)out.constData(); return out.size(); } wkhtmltopdf-0.12.5/src/lib/image_c_bindings_p.hh000066400000000000000000000035001343154624600216060ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __IMAGE_C_BINDINGS_P_HH__ #define __IMAGE_C_BINDINGS_P_HH__ #include "image.h" #include "imageconverter.hh" #include #include "dllbegin.inc" class DLL_LOCAL MyImageConverter: public QObject { Q_OBJECT public: wkhtmltoimage_str_callback warning_cb; wkhtmltoimage_str_callback error_cb; wkhtmltoimage_void_callback phase_changed; wkhtmltoimage_int_callback progress_changed; wkhtmltoimage_int_callback finished_cb; wkhtmltopdf::ImageConverter converter; wkhtmltopdf::settings::ImageGlobal * globalSettings; MyImageConverter(wkhtmltopdf::settings::ImageGlobal * gs, const QString * data); ~MyImageConverter(); public slots: void warning(const QString & message); void error(const QString & message); void phaseChanged(); void progressChanged(int progress); void finished(bool ok); private: MyImageConverter(const MyImageConverter&); }; #include "dllend.inc" #endif //__IMAGE_C_BINDINGS_P_HH__ wkhtmltopdf-0.12.5/src/lib/imageconverter.cc000066400000000000000000000170101343154624600210270ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "imageconverter_p.hh" #include "imagesettings.hh" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN32 #include #include #endif namespace wkhtmltopdf { ImageConverterPrivate::ImageConverterPrivate(ImageConverter & o, wkhtmltopdf::settings::ImageGlobal & s, const QString * data): settings(s), loader(s.loadGlobal, 96, true), out(o) { out.emitCheckboxSvgs(s.loadPage); if (data) inputData = *data; phaseDescriptions.push_back("Loading page"); phaseDescriptions.push_back("Rendering"); phaseDescriptions.push_back("Done"); connect(&loader, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int))); connect(&loader, SIGNAL(loadFinished(bool)), this, SLOT(pagesLoaded(bool))); connect(&loader, SIGNAL(error(QString)), this, SLOT(forwardError(QString))); connect(&loader, SIGNAL(warning(QString)), this, SLOT(forwardWarning(QString))); } void ImageConverterPrivate::beginConvert() { error = false; conversionDone = false; errorCode = 0; progressString = "0%"; loaderObject = loader.addResource(settings.in, settings.loadPage, &inputData); updateWebSettings(loaderObject->page.settings(), settings.web); currentPhase=0; emit out. phaseChanged(); loadProgress(0); loader.load(); } void ImageConverterPrivate::clearResources() { loader.clearResources(); } void ImageConverterPrivate::pagesLoaded(bool ok) { if (errorCode == 0) errorCode = loader.httpErrorCode(); if (!ok) { fail(); return; } // if fmt is empty try to get it from file extension in out if (settings.fmt=="") { if (settings.out == "-") settings.fmt = "jpg"; else { QFileInfo fi(settings.out); settings.fmt = fi.suffix(); } } // check whether image format is supported (for writing) // QImageWriter test; // test.setFormat(settings.fmt); // if (!test.canWrite()) { // if (!settings.quiet)printf("error: file format not supported\n"); // httpErrorCode=DEFAULT; // return false; // } // create webkit frame and load website currentPhase=1; emit out. phaseChanged(); loadProgress(0); QWebFrame * frame = loaderObject->page.mainFrame(); loaderObject->page.mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); loadProgress(25); // Calculate a good width for the image int highWidth=settings.screenWidth; loaderObject->page.setViewportSize(QSize(highWidth, 10)); if (settings.smartWidth && frame->scrollBarMaximum(Qt::Horizontal) > 0) { if (highWidth < 10) highWidth=10; int lowWidth=highWidth; while (frame->scrollBarMaximum(Qt::Horizontal) > 0 && highWidth < 32000) { lowWidth = highWidth; highWidth *= 2; loaderObject->page.setViewportSize(QSize(highWidth, 10)); } while (highWidth - lowWidth > 10) { int t = lowWidth + (highWidth - lowWidth)/2; loaderObject->page.setViewportSize(QSize(t, 10)); if (frame->scrollBarMaximum(Qt::Horizontal) > 0) lowWidth = t; else highWidth = t; } loaderObject->page.setViewportSize(QSize(highWidth, 10)); } loaderObject->page.mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); //Set the right height if (settings.screenHeight > 0) loaderObject->page.setViewportSize(QSize(highWidth, settings.screenHeight)); else loaderObject->page.setViewportSize(QSize(highWidth, frame->contentsSize().height())); QPainter painter; QSvgGenerator generator; QImage image; QFile file; QBuffer buffer(&outputData); QIODevice * dev = &file; bool openOk=true; // output image if (settings.out.isEmpty()) dev = &buffer; else if (settings.out != "-" ) { file.setFileName(settings.out); openOk = file.open(QIODevice::WriteOnly); } else { #ifdef Q_OS_WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif openOk = file.open(stdout, QIODevice::WriteOnly); } if (!openOk) { emit out.error("Could not write to output file"); fail(); } if (settings.crop.left < 0) settings.crop.left = 0; if (settings.crop.top < 0) settings.crop.top = 0; if (settings.crop.width < 0) settings.crop.width = 1000000; if (settings.crop.height < 0) settings.crop.height = 1000000; QRect rect = QRect(QPoint(0,0), loaderObject->page.viewportSize()).intersected( QRect(settings.crop.left,settings.crop.top,settings.crop.width,settings.crop.height)); if (rect.width() == 0 || rect.height() == 0) { emit out.error("Will not output an empty image"); fail(); } if (settings.fmt != "svg") { image = QImage(rect.size(), QImage::Format_ARGB32_Premultiplied); painter.begin(&image); } else { generator.setOutputDevice(dev); generator.setSize(rect.size()); generator.setViewBox(QRect(QPoint(0,0),rect.size())); #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ generator.setViewBoxClip(true); #endif painter.begin(&generator); } if (settings.transparent && (settings.fmt == "png" || settings.fmt == "svg")) { QWebElement e = frame->findFirstElement("body"); e.setStyleProperty("background-color", "transparent"); e.setStyleProperty("background-image", "none"); QPalette pal = loaderObject->page.palette(); pal.setBrush(QPalette::Base, Qt::transparent); loaderObject->page.setPalette(pal); } else { painter.fillRect(QRect(QPoint(0,0),loaderObject->page.viewportSize()), Qt::white); } painter.translate(-rect.left(), -rect.top()); frame->render(&painter); painter.end(); //loadProgress(30); // perform filter(s) //if (settings.crop.width > 0 && settings.crop.height > 0) // image=image.copy(settings.crop.left,settings.crop.top,settings.crop.width,settings.crop.height); //loadProgress(50); //if (settings.scale.width > 0 && settings.scale.height > 0) { // todo: perhaps get more user options to change aspect ration and scaling mode? // image=image.scaled(settings.scale.width,settings.scale.height,Qt::IgnoreAspectRatio,Qt::SmoothTransformation); //} //loadProgress(80); if (settings.fmt != "svg") { QByteArray fmt=settings.fmt.toLatin1(); if (!image.save(dev,fmt.data(), settings.quality)) { emit out.error("Could not save image"); fail(); } } loadProgress(100); currentPhase = 2; emit out.phaseChanged(); conversionDone = true; emit out.finished(true); qApp->exit(0); // quit qt's event handling } Converter & ImageConverterPrivate::outer() { return out; } ImageConverter::~ImageConverter() { delete d; } ConverterPrivate & ImageConverter::priv() { return *d; } ImageConverter::ImageConverter(wkhtmltopdf::settings::ImageGlobal & s, const QString * data) { d = new ImageConverterPrivate(*this, s, data); } const QByteArray & ImageConverter::output() { return d->outputData; } } wkhtmltopdf-0.12.5/src/lib/imageconverter.hh000066400000000000000000000027021343154624600210430ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __IMAGECONVERTER_HH__ #define __IMAGECONVERTER_HH__ #include #include #include namespace wkhtmltopdf { class DLL_LOCAL ImageConverterPrivate; class DLL_PUBLIC ImageConverter: public Converter { Q_OBJECT public: ImageConverter(settings::ImageGlobal & settings, const QString * data=NULL); ~ImageConverter(); const QByteArray & output(); private: ImageConverterPrivate * d; virtual ConverterPrivate & priv(); friend class ImageConverterPrivate; }; #include } #endif //__IMAGECONVERTER_HH__ wkhtmltopdf-0.12.5/src/lib/imageconverter_p.hh000066400000000000000000000032251343154624600213630ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __IMAGECONVERTER_P_HH__ #define __IMAGECONVERTER_P_HH__ #include "converter_p.hh" #include "imageconverter.hh" #include "multipageloader.hh" #include "dllbegin.inc" namespace wkhtmltopdf { class DLL_LOCAL ImageConverterPrivate: public ConverterPrivate { Q_OBJECT public: ImageConverterPrivate(ImageConverter & o, wkhtmltopdf::settings::ImageGlobal & s, const QString * data); wkhtmltopdf::settings::ImageGlobal settings; MultiPageLoader loader; private: QByteArray outputData; QString inputData; ImageConverter & out; void clearResources(); LoaderObject * loaderObject; public slots: void pagesLoaded(bool ok); void beginConvert(); friend class ImageConverter; virtual Converter & outer(); }; } #include "dllend.inc" #endif //__IMAGECONVERTER_P_HH__ wkhtmltopdf-0.12.5/src/lib/imagesettings.cc000066400000000000000000000045071343154624600206670ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "imagesettings.hh" #include "reflect.hh" #include "dllbegin.inc" namespace wkhtmltopdf { namespace settings { template<> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(CropSettings & c) { WKHTMLTOPDF_REFLECT(left); WKHTMLTOPDF_REFLECT(top); WKHTMLTOPDF_REFLECT(width); WKHTMLTOPDF_REFLECT(height); } }; template<> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(ImageGlobal & c) { WKHTMLTOPDF_REFLECT(screenWidth); WKHTMLTOPDF_REFLECT(screenHeight); ReflectClass::add("quiet", new QuietArgBackwardsCompatReflect(c.logLevel)); // Fake the "quiet" argument WKHTMLTOPDF_REFLECT(logLevel); WKHTMLTOPDF_REFLECT(transparent); WKHTMLTOPDF_REFLECT(useGraphics); WKHTMLTOPDF_REFLECT(in); WKHTMLTOPDF_REFLECT(out); WKHTMLTOPDF_REFLECT(fmt); WKHTMLTOPDF_REFLECT(quality); WKHTMLTOPDF_REFLECT(loadGlobal); WKHTMLTOPDF_REFLECT(loadPage); } }; CropSettings::CropSettings(): left(-1), top(-1), width(-1), height(-1) {} ImageGlobal::ImageGlobal(): logLevel(Info), transparent(false), useGraphics(false), in(""), out(""), fmt(""), screenWidth(1024), screenHeight(0), quality(94), smartWidth(true) {} QString ImageGlobal::get(const char * name) { ReflectImpl impl(*this); return impl.get(name); } bool ImageGlobal::set(const char * name, const QString & value) { ReflectImpl impl(*this); return impl.set(name, value); } } } wkhtmltopdf-0.12.5/src/lib/imagesettings.hh000066400000000000000000000043341343154624600206770ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __IMAGESETTINGS_HH__ #define __IMAGESETTINGS_HH__ #include #include #include #include #include namespace wkhtmltopdf { namespace settings { /*! \brief Settings for cropping image */ struct DLL_PUBLIC CropSettings { CropSettings(); //! Cropping left/x coord int left; //! Cropping top/y coord int top; //! Cropping width/w dime int width; //! Cropping height/h dime int height; }; /*! \brief Class holding all user settings. This class holds all the user settings, settings can be filled in by hand, or with other methods. \sa CommandLineParser::parse() */ struct DLL_PUBLIC ImageGlobal { ImageGlobal(); //! Crop related settings CropSettings crop; //! Scale related settings // ScaleSettings scale; LoadGlobal loadGlobal; LoadPage loadPage; Web web; //! Log level LogLevel logLevel; bool transparent; //! Should we use the graphics system bool useGraphics; QString in; //! The file for output QString out; //! The output format QString fmt; //! Set the screen width int screenWidth; //! Set the screen height int screenHeight; //! Image Quality int quality; bool smartWidth; QString get(const char * name); bool set(const char * name, const QString & value); }; #include } } #endif //__IMAGESETTINGS_HH__ wkhtmltopdf-0.12.5/src/lib/lib.def000066400000000000000000000026501343154624600167400ustar00rootroot00000000000000LIBRARY wkhtmltox EXPORTS wkhtmltopdf_init wkhtmltopdf_deinit wkhtmltopdf_extended_qt wkhtmltopdf_version wkhtmltopdf_create_global_settings wkhtmltopdf_destroy_global_settings wkhtmltopdf_create_object_settings wkhtmltopdf_destroy_object_settings wkhtmltopdf_set_global_setting wkhtmltopdf_get_global_setting wkhtmltopdf_set_object_setting wkhtmltopdf_get_object_setting wkhtmltopdf_create_converter wkhtmltopdf_destroy_converter wkhtmltopdf_set_warning_callback wkhtmltopdf_set_error_callback wkhtmltopdf_set_phase_changed_callback wkhtmltopdf_set_progress_changed_callback wkhtmltopdf_set_finished_callback wkhtmltopdf_convert wkhtmltopdf_add_object wkhtmltopdf_current_phase wkhtmltopdf_phase_count wkhtmltopdf_phase_description wkhtmltopdf_progress_string wkhtmltopdf_http_error_code wkhtmltopdf_get_output wkhtmltoimage_init wkhtmltoimage_deinit wkhtmltoimage_extended_qt wkhtmltoimage_version wkhtmltoimage_create_global_settings wkhtmltoimage_set_global_setting wkhtmltoimage_get_global_setting wkhtmltoimage_create_converter wkhtmltoimage_destroy_converter wkhtmltoimage_set_warning_callback wkhtmltoimage_set_error_callback wkhtmltoimage_set_phase_changed_callback wkhtmltoimage_set_progress_changed_callback wkhtmltoimage_set_finished_callback wkhtmltoimage_convert wkhtmltoimage_current_phase wkhtmltoimage_phase_count wkhtmltoimage_phase_description wkhtmltoimage_progress_string wkhtmltoimage_http_error_code wkhtmltoimage_get_output wkhtmltopdf-0.12.5/src/lib/lib.pri000066400000000000000000000034251343154624600167750ustar00rootroot00000000000000# Copyright 2010 wkhtmltopdf authors # # This file is part of wkhtmltopdf. # # wkhtmltopdf is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # wkhtmltopdf is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with wkhtmltopdf. If not, see . DEFINES += BUILDING_DLL #Shared PUBLIC_HEADERS += ../lib/converter.hh ../lib/multipageloader.hh ../lib/dllbegin.inc PUBLIC_HEADERS += ../lib/dllend.inc ../lib/loadsettings.hh ../lib/websettings.hh PUBLIC_HEADERS += ../lib/utilities.hh HEADERS += ../lib/multipageloader_p.hh ../lib/converter_p.hh SOURCES += ../lib/loadsettings.cc ../lib/logging.cc ../lib/multipageloader.cc \ ../lib/tempfile.cc ../lib/converter.cc ../lib/websettings.cc \ ../lib/reflect.cc ../lib/utilities.cc #Pdf PUBLIC_HEADERS += ../lib/pdfconverter.hh ../lib/pdfsettings.hh HEADERS += ../lib/pdfconverter_p.hh SOURCES += ../lib/pdfsettings.cc ../lib/pdfconverter.cc \ ../lib/outline.cc ../lib/tocstylesheet.cc PUBLIC_HEADERS += ../lib/imageconverter.hh ../lib/imagesettings.hh HEADERS += ../lib/imageconverter_p.hh SOURCES += ../lib/imagesettings.cc ../lib/imageconverter.cc #C-Bindings PUBLIC_HEADERS += ../lib/pdf.h ../lib/image.h HEADERS += ../lib/pdf_c_bindings_p.hh ../lib/image_c_bindings_p.hh SOURCES += ../lib/pdf_c_bindings.cc ../lib/image_c_bindings.cc HEADERS += $$PUBLIC_HEADERS wkhtmltopdf-0.12.5/src/lib/lib.pro000066400000000000000000000022511343154624600167770ustar00rootroot00000000000000# Copyright 2010 wkhtmltopdf authors # # This file is part of wkhtmltopdf. # # wkhtmltopdf is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # wkhtmltopdf is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with wkhtmltopdf. If not, see . TEMPLATE = lib CONFIG += dll include(../../common.pri) include(lib.pri) DEF_FILE = lib.def CONFIG(static, shared|static): DEFINES += QT_NODLL headers.target=headers headers.files=*.h *.inc headers.path=$$INSTALLBASE/include/wkhtmltox QMAKE_EXTRA_TARGETS += headers INSTALLS += headers windows: CONFIG += skip_target_version_ext TARGET=wkhtmltox INSTALLS += target DESTDIR = ../../bin !windows: target.path=$$INSTALLBASE/lib else: target.path=$$INSTALLBASE/bin wkhtmltopdf-0.12.5/src/lib/loadsettings.cc000066400000000000000000000075031343154624600205230ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2012 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifdef _MSC_VER #define strcasecmp _stricmp #endif #include "loadsettings.hh" #include #include namespace wkhtmltopdf { namespace settings { QList LoadPage::mediaFilesExtensions = QList () << "css" << "js" << "png" << "jpg" << "jpeg" << "gif"; LoadPage::LoadErrorHandling strToLoadErrorHandling(const char * s, bool * ok) { if (ok) *ok = true; if (!strcasecmp(s, "abort")) return LoadPage::abort; if (!strcasecmp(s, "skip")) return LoadPage::skip; if (!strcasecmp(s, "ignore")) return LoadPage::ignore; *ok = false; return LoadPage::abort; } QString loadErrorHandlingToStr(LoadPage::LoadErrorHandling leh) { switch (leh) { case LoadPage::abort: return "abort"; case LoadPage::skip: return "skip"; case LoadPage::ignore: return "ignore"; } throw std::logic_error("Internal error in loadErrorHandlingToStr"); } /*! Read proxy settings from a string, the grammar is described in the manual \param proxy the proxy string to parse \param ok If supplied indicates whether the proxy was valid */ Proxy strToProxy(const char * proxy, bool * ok) { Proxy p; if (ok) *ok=true; //Allow users to use no proxy, even if one is specified in the env if (!strcmp(proxy,"none")) { p.host = ""; return p; } p.type = QNetworkProxy::HttpProxy; //Read proxy type bit "http://" or "socks5://" if (!strncmp(proxy,"http://",7)) { proxy += 7; } else if (!strncmp(proxy,"socks5://",9)) { p.type = QNetworkProxy::Socks5Proxy; proxy += 9; } //Read username and password char * val = (char *) strrchr(proxy,'@'); p.user = p.password = ""; if (val != NULL) { p.user = QString(proxy).left(val-proxy); proxy = val+1; int idx = p.user.indexOf(':'); if (idx != -1) { p.password = p.user.mid(idx+1); p.user = p.user.left(idx); } } //Read hostname and port val = (char *) strchr(proxy,':'); p.port = 1080; //Default proxy port if (val == NULL) p.host = proxy; else { p.port = QString(val+1).toInt(ok); if (p.port < 0 || p.port > 65535) { p.port = 1080; *ok = false; } p.host = QString(proxy).left(val-proxy); } if (ok && p.host.size() == 0) *ok = false; return p; } QString proxyToStr(const Proxy & p) { QString res=""; if (p.type == QNetworkProxy::HttpProxy) res += "http://"; else if (p.type == QNetworkProxy::Socks5Proxy) res += "socks5://"; if (!p.user.isEmpty()) { res += "@" + p.user; if (!p.password.isEmpty()) res += ":" + p.password; } res += p.host; if (!p.host.isEmpty()) res += ":" + QString::number(p.port); return res; } Proxy::Proxy(): type(QNetworkProxy::NoProxy), port(-1), host(), user(), password() {} LoadGlobal::LoadGlobal(): cookieJar("") {} LoadPage::LoadPage(): jsdelay(200), windowStatus(""), zoomFactor(1.0), repeatCustomHeaders(false), blockLocalFileAccess(false), stopSlowScripts(true), debugJavascript(false), loadErrorHandling(abort), mediaLoadErrorHandling(ignore), cacheDir(""), proxyHostNameLookup(false) {}; } } wkhtmltopdf-0.12.5/src/lib/loadsettings.hh000066400000000000000000000075171343154624600205420ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2012 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __LOADSETTINGS_HH__ #define __LOADSETTINGS_HH__ #include #include #include namespace wkhtmltopdf { namespace settings { /*! \brief Settings considering proxy */ struct DLL_PUBLIC Proxy { Proxy(); //! Type of proxy to use QNetworkProxy::ProxyType type; //! The port of the proxy to use int port; //! The host name of the proxy to use or NULL QString host; //! Username for the said proxy or NULL QString user; //! Password for the said proxy or NULL QString password; }; struct DLL_PUBLIC PostItem { QString name; QString value; bool file; }; struct DLL_PUBLIC LoadGlobal { LoadGlobal(); //! Path of the cookie jar file QString cookieJar; }; struct DLL_PUBLIC LoadPage { LoadPage(); enum LoadErrorHandling { abort, skip, ignore }; //! Username used for http auth login QString username; //! Password used for http auth login QString password; //! Path to the ssl client cert private key in OpenSSL PEM format QString clientSslKeyPath; //! Password to ssl client cert private key QString clientSslKeyPassword; //! Path to the ssl client cert public key in OpenSSL PEM format, optionally followed by intermediate ca and trusted certs QString clientSslCrtPath; //! How many milliseconds should we wait for a Javascript redirect int jsdelay; //! What window.status value should we wait for QString windowStatus; //! What zoom factor should we apply when printing // TODO MOVE float zoomFactor; //! Map of custom header variables QList< QPair > customHeaders; //! Set if the custom header should be repeated for each resource request bool repeatCustomHeaders; //! Map of cookies QList< QPair > cookies; QList< PostItem > post; //! Block access to local files for the given page bool blockLocalFileAccess; //! If access to local files is not allowed in general, allow it for these files QList< QString > allowed; //! Stop Javascript from running too long bool stopSlowScripts; //! Output Javascript debug messages bool debugJavascript; //! What should we do about load errors LoadErrorHandling loadErrorHandling; LoadErrorHandling mediaLoadErrorHandling; //! Proxy related settings Proxy proxy; //! Additional javascript to run on a page once it has loaded QList< QString > runScript; QString checkboxSvg; QString checkboxCheckedSvg; QString radiobuttonSvg; QString radiobuttonCheckedSvg; QString cacheDir; static QList mediaFilesExtensions; // Hosts to bypass QList< QString > bypassProxyForHosts; //! Whether to use the proxy for resolving hostnames bool proxyHostNameLookup; }; DLL_PUBLIC LoadPage::LoadErrorHandling strToLoadErrorHandling(const char * s, bool * ok=0); DLL_PUBLIC QString loadErrorHandlingToStr(LoadPage::LoadErrorHandling leh); DLL_PUBLIC Proxy strToProxy(const char * s, bool * ok=0); DLL_PUBLIC QString proxyToStr(const Proxy & proxy); } } #include #endif //__LOADSETTINGS_HH__ wkhtmltopdf-0.12.5/src/lib/logging.cc000066400000000000000000000035431343154624600174510ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "logging.hh" #include #include #include namespace wkhtmltopdf { namespace settings { // Centralized name-to-enum value mapping QMap logLevelMap() { QMap res; res["none"] = None; res["error"] = Error; res["warn"] = Warn; res["info"] = Info; return res; } QMap logLevels = logLevelMap(); LogLevel strToLogLevel(const char * s, bool * ok) { for (QMap::const_iterator i = logLevels.begin(); i != logLevels.end(); ++i) { if (i.key().compare(s, Qt::CaseInsensitive) != 0) continue; if (ok) *ok = true; return i.value(); } if (ok) *ok = false; return Info; } QString logLevelToStr(const LogLevel & l, bool * ok) { for (QMap::const_iterator i = logLevels.begin(); i != logLevels.end(); ++i) { if (i.value() != l) continue; if (ok) *ok = true; return i.key(); } if (ok) *ok = false; return QString(); } } } #include wkhtmltopdf-0.12.5/src/lib/logging.hh000066400000000000000000000024061343154624600174600ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __LOGGING_HH__ #define __LOGGING_HH__ #include #include #include namespace wkhtmltopdf { namespace settings { enum LogLevel { None, Error, Warn, Info }; DLL_PUBLIC LogLevel strToLogLevel(const char * s, bool * ok=0); DLL_PUBLIC QString logLevelToStr(const LogLevel & l, bool * ok=0); } } #include #endif //__LOGGING_HH__ wkhtmltopdf-0.12.5/src/lib/multipageloader.cc000066400000000000000000000622631343154624600212050ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "multipageloader_p.hh" #include #include #include #include #include #include #include #include #if (QT_VERSION >= 0x050000 && !defined QT_NO_SSL) || !defined QT_NO_OPENSSL #include #include #include #endif #if QT_VERSION >= 0x050000 #include #endif namespace wkhtmltopdf { /*! \file multipageloader.hh \brief Defines the MultiPageLoader class */ /*! \file multipageloader_p.hh \brief Defines the MultiPageLoaderPrivate class */ LoaderObject::LoaderObject(QWebPage & p): page(p), skip(false) {}; MyNetworkAccessManager::MyNetworkAccessManager(const settings::LoadPage & s): disposed(false), settings(s) { if ( !s.cacheDir.isEmpty() ){ QNetworkDiskCache *cache = new QNetworkDiskCache(this); cache->setCacheDirectory(s.cacheDir); QNetworkAccessManager::setCache(cache); } } void MyNetworkAccessManager::dispose() { disposed = true; } void MyNetworkAccessManager::allow(QString path) { QString x = QFileInfo(path).canonicalFilePath(); if (x.isEmpty()) return; allowed.insert(x); } QNetworkReply * MyNetworkAccessManager::createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData) { if (disposed) { emit warning("Received createRequest signal on a disposed ResourceObject's NetworkAccessManager. " "This might be an indication of an iframe taking too long to load."); // Needed to avoid race conditions by spurious network requests // by scripts or iframes taking too long to load. QNetworkRequest r2 = req; r2.setUrl(QUrl("about:blank")); return QNetworkAccessManager::createRequest(op, r2, outgoingData); } bool isLocalFileAccess = req.url().scheme().length() <= 1 || req.url().scheme() == "file"; if (isLocalFileAccess && settings.blockLocalFileAccess) { bool ok=false; QString path = QFileInfo(req.url().toLocalFile()).canonicalFilePath(); QString old = ""; while (path != old) { if (allowed.contains(path)) { ok=true; break; } old = path; path = QFileInfo(path).path(); } if (!ok) { QNetworkRequest r2 = req; emit warning(QString("Blocked access to file %1").arg(QFileInfo(req.url().toLocalFile()).canonicalFilePath())); r2.setUrl(QUrl("about:blank")); return QNetworkAccessManager::createRequest(op, r2, outgoingData); } } QNetworkRequest r3 = req; if (settings.repeatCustomHeaders) { typedef QPair HT; foreach (const HT & j, settings.customHeaders) r3.setRawHeader(j.first.toLatin1(), j.second.toLatin1()); } #if (QT_VERSION >= 0x050000 && !defined QT_NO_SSL) || !defined QT_NO_OPENSSL if(!settings.clientSslKeyPath.isEmpty() && !settings.clientSslKeyPassword.isEmpty() && !settings.clientSslCrtPath.isEmpty()){ QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration(); QFile keyFile(settings.clientSslKeyPath); if(keyFile.open(QFile::ReadOnly)){ QSslKey key(&keyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, settings.clientSslKeyPassword.toUtf8()); sslConfig.setPrivateKey(key); keyFile.close(); QList chainCerts = QSslCertificate::fromPath(settings.clientSslCrtPath.toLatin1(), QSsl::Pem, QRegExp::FixedString); QList cas = sslConfig.caCertificates(); cas.append(chainCerts); if(!chainCerts.isEmpty()){ sslConfig.setLocalCertificate(chainCerts.first()); sslConfig.setCaCertificates(cas); r3.setSslConfiguration(sslConfig); } } } #endif return QNetworkAccessManager::createRequest(op, r3, outgoingData); } MyNetworkProxyFactory::MyNetworkProxyFactory (QNetworkProxy proxy, QList bph): bypassHosts(bph), originalProxy(QList() << proxy), noProxy(QList() << QNetworkProxy(QNetworkProxy::DefaultProxy)){} QList MyNetworkProxyFactory::queryProxy (const QNetworkProxyQuery & query) { QString host = query.url().host(); foreach (const QString & bypassHost, bypassHosts) { if (host.compare(bypassHost, Qt::CaseInsensitive) == 0) return noProxy; } return originalProxy; } MyQWebPage::MyQWebPage(ResourceObject & res): resource(res) {} void MyQWebPage::javaScriptAlert(QWebFrame *, const QString & msg) { resource.warning(QString("Javascript alert: %1").arg(msg)); } bool MyQWebPage::javaScriptConfirm(QWebFrame *, const QString & msg) { resource.warning(QString("Javascript confirm: %1 (answered yes)").arg(msg)); return true; } bool MyQWebPage::javaScriptPrompt(QWebFrame *, const QString & msg, const QString & defaultValue, QString * result) { resource.warning(QString("Javascript prompt: %1 (answered %2)").arg(msg,defaultValue)); result = (QString*)&defaultValue; Q_UNUSED(result); return true; } void MyQWebPage::javaScriptConsoleMessage(const QString & message, int lineNumber, const QString & sourceID) { if (resource.settings.debugJavascript) resource.warning(QString("%1:%2 %3").arg(sourceID).arg(lineNumber).arg(message)); } bool MyQWebPage::shouldInterruptJavaScript() { if (resource.settings.stopSlowScripts) { resource.warning("A slow script was stopped"); return true; } return false; } ResourceObject::ResourceObject(MultiPageLoaderPrivate & mpl, const QUrl & u, const settings::LoadPage & s): networkAccessManager(s), url(u), loginTry(0), progress(0), finished(false), signalPrint(false), multiPageLoader(mpl), webPage(*this), lo(webPage), httpErrorCode(0), settings(s) { connect(&networkAccessManager, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator *)),this, SLOT(handleAuthenticationRequired(QNetworkReply *, QAuthenticator *))); foreach (const QString & path, s.allowed) networkAccessManager.allow(path); if (url.scheme() == "file") networkAccessManager.allow(url.toLocalFile()); connect(&webPage, SIGNAL(loadStarted()), this, SLOT(loadStarted())); connect(&webPage, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int))); connect(&webPage, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool))); connect(&webPage, SIGNAL(printRequested(QWebFrame*)), this, SLOT(printRequested(QWebFrame*))); //If some ssl error occurs we want sslErrors to be called, so the we can ignore it connect(&networkAccessManager, SIGNAL(sslErrors(QNetworkReply*, const QList&)),this, SLOT(sslErrors(QNetworkReply*, const QList&))); connect(&networkAccessManager, SIGNAL(finished (QNetworkReply *)), this, SLOT(amfinished (QNetworkReply *) ) ); connect(&networkAccessManager, SIGNAL(warning(const QString &)), this, SLOT(warning(const QString &))); connect(&networkAccessManager, SIGNAL(error(const QString &)), this, SLOT(error(const QString &))); networkAccessManager.setCookieJar(multiPageLoader.cookieJar); //If we must use a proxy, create a host of objects if (!settings.proxy.host.isEmpty()) { QNetworkProxy proxy; proxy.setHostName(settings.proxy.host); proxy.setPort(settings.proxy.port); proxy.setType(settings.proxy.type); if (settings.proxy.type == QNetworkProxy::HttpProxy) { QNetworkProxy::Capabilities capabilities = QNetworkProxy::CachingCapability | QNetworkProxy::TunnelingCapability; if (settings.proxyHostNameLookup) capabilities |= QNetworkProxy::HostNameLookupCapability; proxy.setCapabilities(capabilities); } if (!settings.proxy.user.isEmpty()) proxy.setUser(settings.proxy.user); if (!settings.proxy.password.isEmpty()) proxy.setPassword(settings.proxy.password); if (!settings.bypassProxyForHosts.isEmpty()) networkAccessManager.setProxyFactory( new MyNetworkProxyFactory(proxy, settings.bypassProxyForHosts)); else networkAccessManager.setProxy(proxy); } webPage.setNetworkAccessManager(&networkAccessManager); #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ double devicePixelRatio = multiPageLoader.dpi / 96.; // The used version of WebKit always renders at 96 DPI when no zoom is applied. It does not fully support a device pixel ratio != 1 natively. webPage.mainFrame()->setZoomFactor(devicePixelRatio * settings.zoomFactor); // Zoom in the page to achieve a higher DPI. webPage.setDevicePixelRatio(devicePixelRatio); // Fix CSS media queries (does not affect anything else). #endif } /*! * Once loading starting, this is called */ void ResourceObject::loadStarted() { if (finished == true) { ++multiPageLoader.loading; finished = false; } if (multiPageLoader.loadStartedEmitted) return; multiPageLoader.loadStartedEmitted=true; emit multiPageLoader.outer.loadStarted(); } /*! * Called when the page is loading, display some progress to the using * \param progress the loading progress in percent */ void ResourceObject::loadProgress(int p) { // If we are finished, ignore this signal. if (finished || multiPageLoader.resources.size() <= 0) { warning("A finished ResourceObject received a loading progress signal. " "This might be an indication of an iframe taking too long to load."); return; } multiPageLoader.progressSum -= progress; progress = p; multiPageLoader.progressSum += progress; emit multiPageLoader.outer.loadProgress(multiPageLoader.progressSum / multiPageLoader.resources.size()); } void ResourceObject::loadFinished(bool ok) { // If we are finished, this might be a potential bug. if (finished || multiPageLoader.resources.size() <= 0) { warning("A finished ResourceObject received a loading finished signal. " "This might be an indication of an iframe taking too long to load."); return; } multiPageLoader.hasError = multiPageLoader.hasError || (!ok && settings.loadErrorHandling == settings::LoadPage::abort); if (!ok) { if (settings.loadErrorHandling == settings::LoadPage::abort) error(QString("Failed loading page ") + url.toString() + " (sometimes it will work just to ignore this error with --load-error-handling ignore)"); else if (settings.loadErrorHandling == settings::LoadPage::skip) { warning(QString("Failed loading page ") + url.toString() + " (skipped)"); lo.skip = true; } else warning(QString("Failed loading page ") + url.toString() + " (ignored)"); } bool isMain = multiPageLoader.isMainLoader; // Evaluate extra user supplied javascript for the main loader if (isMain) foreach (const QString & str, settings.runScript) webPage.mainFrame()->evaluateJavaScript(str); // XXX: If loading failed there's no need to wait // for javascript on this resource. if (!ok || signalPrint || settings.jsdelay == 0) loadDone(); else if (isMain && !settings.windowStatus.isEmpty()) waitWindowStatus(); else QTimer::singleShot(settings.jsdelay, this, SLOT(loadDone())); } void ResourceObject::waitWindowStatus() { QString windowStatus = webPage.mainFrame()->evaluateJavaScript("window.status").toString(); //warning(QString("window.status:" + windowStatus + " settings.windowStatus:" + settings.windowStatus)); if (windowStatus != settings.windowStatus) { QTimer::singleShot(50, this, SLOT(waitWindowStatus())); } else { QTimer::singleShot(settings.jsdelay, this, SLOT(loadDone())); } } void ResourceObject::printRequested(QWebFrame *) { signalPrint=true; loadDone(); } void ResourceObject::loadDone() { if (finished) return; finished=true; // Ensure no more loading goes.. webPage.triggerAction(QWebPage::Stop); webPage.triggerAction(QWebPage::StopScheduledPageRefresh); networkAccessManager.dispose(); //disconnect(this, 0, 0, 0); --multiPageLoader.loading; if (multiPageLoader.loading == 0) multiPageLoader.loadDone(); } /*! * Called when the page requires authentication, fills in the username * and password supplied on the command line */ void ResourceObject::handleAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator) { Q_UNUSED(reply); // XXX: Avoid calling 'reply->abort()' from within this signal. // As stated by doc, request would be finished when no // user/pass properties are assigned to authenticator object. // See: http://qt-project.org/doc/qt-5.0/qtnetwork/qnetworkaccessmanager.html#authenticationRequired if (settings.username.isEmpty()) { //If no username is given, complain the such is required error("Authentication Required"); } else if (loginTry >= 2) { //If the login has failed a sufficient number of times, //the username or password must be wrong error("Invalid username or password"); } else { authenticator->setUser(settings.username); authenticator->setPassword(settings.password); ++loginTry; } } void ResourceObject::warning(const QString & str) { emit multiPageLoader.outer.warning(str); } void ResourceObject::error(const QString & str) { emit multiPageLoader.outer.error(str); } /*! * Track and handle network errors * \param reply The networkreply that has finished */ void ResourceObject::amfinished(QNetworkReply * reply) { int networkStatus = reply->error(); int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if ((networkStatus != 0 && networkStatus != 5) || (httpStatus > 399 && httpErrorCode == 0)) { QFileInfo fi(reply->url().toString()); QString extension = fi.completeSuffix().toLower().remove(QRegExp("\\?.*$")); bool mediaFile = settings::LoadPage::mediaFilesExtensions.contains(extension); if ( ! mediaFile) { // XXX: Notify network errors as higher priority than HTTP errors. // QT's QNetworkReply::NetworkError enum uses values overlapping // HTTP status codes, so adding 1000 to QT's codes will avoid // confusion. Also a network error at this point will probably mean // no HTTP access at all, so we want network errors to be reported // with a higher priority than HTTP ones. // See: http://doc-snapshot.qt-project.org/4.8/qnetworkreply.html#NetworkError-enum error(QString("Failed to load %1, with network status code %2 and http status code %3 - %4") .arg(reply->url().toString()).arg(networkStatus).arg(httpStatus).arg(reply->errorString())); httpErrorCode = networkStatus > 0 ? (networkStatus + 1000) : httpStatus; return; } if (settings.mediaLoadErrorHandling == settings::LoadPage::abort) { httpErrorCode = networkStatus > 0 ? (networkStatus + 1000) : httpStatus; error(QString("Failed to load ") + reply->url().toString() + ", with code: " + QString::number(httpErrorCode) + " (sometimes it will work just to ignore this error with --load-media-error-handling ignore)"); } else { warning(QString("Failed to load %1 (%2)") .arg(reply->url().toString()) .arg(settings::loadErrorHandlingToStr(settings.mediaLoadErrorHandling)) ); } } } /*! * Handle any ssl error by ignoring */ void ResourceObject::sslErrors(QNetworkReply *reply, const QList &) { //We ignore any ssl error, as it is next to impossible to send or receive //any private information with wkhtmltopdf anyhow, seeing as you cannot authenticate reply->ignoreSslErrors(); warning("SSL error ignored"); } void ResourceObject::load() { finished=false; ++multiPageLoader.loading; bool hasFiles=false; foreach (const settings::PostItem & pi, settings.post) hasFiles |= pi.file; QByteArray postData; QString boundary; if (hasFiles) { boundary = QUuid::createUuid().toString().remove('-').remove('{').remove('}'); foreach (const settings::PostItem & pi, settings.post) { //TODO escape values here postData.append("--"); postData.append(boundary); postData.append("\ncontent-disposition: form-data; name=\""); postData.append(pi.name); postData.append('\"'); if (pi.file) { QFile f(pi.value); if (!f.open(QIODevice::ReadOnly) ) { error(QString("Unable to open file ")+pi.value); multiPageLoader.fail(); } postData.append("; filename=\""); postData.append( QFileInfo(pi.value).fileName()); postData.append("\"\n\n"); postData.append( f.readAll() ); //TODO ADD MIME TYPE } else { postData.append("\n\n"); postData.append(pi.value); } postData.append('\n'); } if (!postData.isEmpty()) { postData.append("--"); postData.append(boundary); postData.append("--\n"); } } else { #if QT_VERSION >= 0x050000 QUrlQuery q; foreach (const settings::PostItem & pi, settings.post) q.addQueryItem(pi.name, pi.value); postData = q.query(QUrl::FullyEncoded).toLocal8Bit(); #else QUrl u; foreach (const settings::PostItem & pi, settings.post) u.addQueryItem(pi.name, pi.value); postData = u.encodedQuery(); #endif } multiPageLoader.cookieJar->clearExtraCookies(); typedef QPair SSP; foreach (const SSP & pair, settings.cookies) multiPageLoader.cookieJar->useCookie(url, pair.first, pair.second); QNetworkRequest r = QNetworkRequest(url); typedef QPair HT; foreach (const HT & j, settings.customHeaders) r.setRawHeader(j.first.toLatin1(), j.second.toLatin1()); if (postData.isEmpty()) webPage.mainFrame()->load(r); else { if (hasFiles) r.setHeader(QNetworkRequest::ContentTypeHeader, QString("multipart/form-data, boundary=")+boundary); webPage.mainFrame()->load(r, QNetworkAccessManager::PostOperation, postData); } } void MyCookieJar::clearExtraCookies() { extraCookies.clear(); } void MyCookieJar::useCookie(const QUrl &, const QString & name, const QString & value) { extraCookies.push_back(QNetworkCookie(name.toUtf8(), value.toUtf8())); } QList MyCookieJar::cookiesForUrl(const QUrl & url) const { QList list = QNetworkCookieJar::cookiesForUrl(url); list.append(extraCookies); return list; } void MyCookieJar::loadFromFile(const QString & path) { QFile cookieJar(path); if (cookieJar.open(QIODevice::ReadOnly | QIODevice::Text) ) setAllCookies(QNetworkCookie::parseCookies(cookieJar.readAll())); } void MyCookieJar::saveToFile(const QString & path) { QFile cookieJar(path); if (cookieJar.open(QIODevice::WriteOnly | QIODevice::Text) ) foreach (const QNetworkCookie & cookie, allCookies()) { cookieJar.write(cookie.toRawForm()); cookieJar.write(";\n"); } } void MultiPageLoaderPrivate::loadDone() { if (!settings.cookieJar.isEmpty()) cookieJar->saveToFile(settings.cookieJar); if (!finishedEmitted) { finishedEmitted = true; emit outer.loadFinished(!hasError); } } /*! * Copy a file from some place to another * \param src The source to copy from * \param dst The destination to copy to */ bool MultiPageLoader::copyFile(QFile & src, QFile & dst) { // TODO enable again when // http://bugreports.qt.nokia.com/browse/QTBUG-6894 // is fixed // QByteArray buf(1024*1024*5,0); // while ( qint64 r=src.read(buf.data(),buf.size())) { // if (r == -1) return false; // if (dst.write(buf.data(),r) != r) return false; // } if (dst.write( src.readAll() ) == -1) return false; src.close(); dst.close(); return true; } MultiPageLoaderPrivate::MultiPageLoaderPrivate(const settings::LoadGlobal & s, int dpi_, MultiPageLoader & o): outer(o), settings(s), dpi(dpi_) { cookieJar = new MyCookieJar(); if (!settings.cookieJar.isEmpty()) cookieJar->loadFromFile(settings.cookieJar); } MultiPageLoaderPrivate::~MultiPageLoaderPrivate() { clearResources(); } LoaderObject * MultiPageLoaderPrivate::addResource(const QUrl & url, const settings::LoadPage & page) { ResourceObject * ro = new ResourceObject(*this, url, page); resources.push_back(ro); return &ro->lo; } void MultiPageLoaderPrivate::load() { progressSum=0; loadStartedEmitted=false; finishedEmitted=false; hasError=false; loading=0; for (int i=0; i < resources.size(); ++i) resources[i]->load(); if (resources.size() == 0) loadDone(); } void MultiPageLoaderPrivate::clearResources() { while (resources.size() > 0) { // XXX: Using deleteLater() to dispose // resources, to avoid race conditions with // pending signals reaching a deleted resource. // Also, and we must avoid calling clear() // on resources list, is it tries to delete // each objet on removal. ResourceObject *tmp = resources.takeFirst(); tmp->deleteLater(); } tempIn.removeAll(); } void MultiPageLoaderPrivate::cancel() { //foreach (QWebPage * page, pages) // page->triggerAction(QWebPage::Stop); } void MultiPageLoaderPrivate::fail() { hasError = true; cancel(); clearResources(); } /*! \brief Construct a multipage loader object, load settings read from the supplied settings \param s The settings to be used while loading pages */ MultiPageLoader::MultiPageLoader(settings::LoadGlobal & s, int dpi, bool mainLoader): d(new MultiPageLoaderPrivate(s, dpi, *this)) { d->isMainLoader = mainLoader; } MultiPageLoader::~MultiPageLoader() { MultiPageLoaderPrivate *tmp = d; d = 0; tmp->deleteLater(); } /*! \brief Add a resource, to be loaded described by a string @param string Url describing the resource to load */ LoaderObject * MultiPageLoader::addResource(const QString & string, const settings::LoadPage & s, const QString * data) { QString url=string; if (data && !data->isEmpty()) { url = d->tempIn.create(".html"); QFile tmp(url); if (!tmp.open(QIODevice::WriteOnly) || tmp.write(data->toUtf8())==0) { emit error("Unable to create temporary file"); return NULL; } } else if (url == "-") { QFile in; in.open(stdin,QIODevice::ReadOnly); url = d->tempIn.create(".html"); QFile tmp(url); if (!tmp.open(QIODevice::WriteOnly) || !copyFile(in, tmp)) { emit error("Unable to create temporary file"); return NULL; } } return addResource(guessUrlFromString(url), s); } /*! \brief Add a page to be loaded @param url Url of the page to load */ LoaderObject * MultiPageLoader::addResource(const QUrl & url, const settings::LoadPage & s) { return d->addResource(url, s); } /*! \brief Guess a url, by looking at a string (shamelessly copied from Arora Project) \param string The string the is suppose to be some kind of url */ QUrl MultiPageLoader::guessUrlFromString(const QString &string) { QString urlStr = string.trimmed(); // check if the string is just a host with a port QRegExp hostWithPort(QLatin1String("^[a-zA-Z\\.]+\\:[0-9]*$")); if (hostWithPort.exactMatch(urlStr)) urlStr = QLatin1String("http://") + urlStr; // Check if it looks like a qualified URL. Try parsing it and see. QRegExp test(QLatin1String("^[a-zA-Z]+\\://.*")); bool hasSchema = test.exactMatch(urlStr); if (hasSchema) { bool isAscii = true; foreach (const QChar &c, urlStr) { if (c >= 0x80) { isAscii = false; break; } } QUrl url; if (isAscii) { url = QUrl::fromEncoded(urlStr.toLatin1(), QUrl::TolerantMode); } else { url = QUrl(urlStr, QUrl::TolerantMode); } if (url.isValid()) return url; } // Might be a file. if (QFile::exists(urlStr)) { QFileInfo info(urlStr); return QUrl::fromLocalFile(info.absoluteFilePath()); } // Might be a shorturl - try to detect the schema. if (!hasSchema) { int dotIndex = urlStr.indexOf(QLatin1Char('.')); if (dotIndex != -1) { QString prefix = urlStr.left(dotIndex).toLower(); QString schema = (prefix == QLatin1String("ftp")) ? prefix : QLatin1String("http"); QUrl url(schema + QLatin1String("://") + urlStr, QUrl::TolerantMode); if (url.isValid()) return url; } } // Fall back to QUrl's own tolerant parser. QUrl url = QUrl(string, QUrl::TolerantMode); // finally for cases where the user just types in a hostname add http if (url.scheme().isEmpty()) url = QUrl(QLatin1String("http://") + string, QUrl::TolerantMode); return url; } /*! \brief Return the most severe http error code returned during loading */ int MultiPageLoader::httpErrorCode() { int res=0; foreach (const ResourceObject * ro, d->resources) if (ro->httpErrorCode > res) res = ro->httpErrorCode; return res; } /*! \brief Begin loading all the resources added */ void MultiPageLoader::load() { d->load(); } /*! \brief Clear all the resources */ void MultiPageLoader::clearResources() { d->clearResources(); } /*! \brief Cancel the loading of the pages */ void MultiPageLoader::cancel() { d->cancel(); } /*! \fn MultiPageLoader::loadFinished(bool ok) \brief Signal emitted when all pages have been loaded \param ok True if all the pages have been loaded successfully */ /*! \fn MultiPageLoader::loadProgress(int progress) \brief Signal emitted once load has progressed \param progress Progress in percent */ /*! \fn MultiPageLoader::loadStarted() \brief Signal emitted when loading has started */ /*! \fn void MultiPageLoader::warning(QString text) \brief Signal emitted when a none fatal warning has occurred \param text A string describing the warning */ /*! \fn void MultiPageLoader::error(QString text) \brief Signal emitted when a fatal error has occurred \param text A string describing the error */ } wkhtmltopdf-0.12.5/src/lib/multipageloader.hh000066400000000000000000000043231343154624600212100ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __MULTIPAGELOADER_HH__ #define __MULTIPAGELOADER_HH__ #include #include #include #if QT_VERSION >= 0x050000 #include #else #include #endif #include #include namespace wkhtmltopdf { class DLL_LOCAL MyQWebPage; class DLL_LOCAL LoaderObject { public: QWebPage & page; bool skip; LoaderObject(QWebPage & page); }; class DLL_LOCAL MultiPageLoaderPrivate; class DLL_LOCAL MultiPageLoader: public QObject { Q_OBJECT public: MultiPageLoader(settings::LoadGlobal & s, int dpi, bool mainLoader = false); ~MultiPageLoader(); LoaderObject * addResource(const QString & url, const settings::LoadPage & settings, const QString * data=NULL); LoaderObject * addResource(const QUrl & url, const settings::LoadPage & settings); static QUrl guessUrlFromString(const QString &string); int httpErrorCode(); static bool copyFile(QFile & src, QFile & dst); public slots: void load(); void clearResources(); void cancel(); signals: void loadFinished(bool ok); void loadProgress(int progress); void loadStarted(); void warning(QString text); void error(QString text); private: MultiPageLoaderPrivate * d; friend class MultiPageLoaderPrivate; friend class MyQWebPage; friend class ResourceObject; }; } #include #endif //__MULTIPAGELOADER_HH__ wkhtmltopdf-0.12.5/src/lib/multipageloader_p.hh000066400000000000000000000111241343154624600215240ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __MULTIPAGELOADER_P_HH__ #define __MULTIPAGELOADER_P_HH__ #include "multipageloader.hh" #include "tempfile.hh" #include #include #include #include #include #include #include #include #include "dllbegin.inc" namespace wkhtmltopdf { class DLL_LOCAL MyNetworkProxyFactory: public QObject, public QNetworkProxyFactory { Q_OBJECT private: QList bypassHosts; QList originalProxy, noProxy; public: MyNetworkProxyFactory(QNetworkProxy defaultProxy, QList bypassHosts); QList queryProxy (const QNetworkProxyQuery & query); }; class DLL_LOCAL MyNetworkAccessManager: public QNetworkAccessManager { Q_OBJECT private: bool disposed; QSet allowed; const settings::LoadPage & settings; public: void dispose(); void allow(QString path); MyNetworkAccessManager(const settings::LoadPage & s); QNetworkReply * createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0); signals: void warning(const QString & text); void error(const QString & text); }; class DLL_LOCAL MultiPageLoaderPrivate; class DLL_LOCAL ResourceObject; class DLL_LOCAL MyQWebPage: public QWebPage { Q_OBJECT ; private: ResourceObject & resource; public: MyQWebPage(ResourceObject & res); virtual void javaScriptAlert(QWebFrame * frame, const QString & msg); virtual bool javaScriptConfirm(QWebFrame * frame, const QString & msg); virtual bool javaScriptPrompt(QWebFrame * frame, const QString & msg, const QString & defaultValue, QString * result); virtual void javaScriptConsoleMessage(const QString & message, int lineNumber, const QString & sourceID); public slots: bool shouldInterruptJavaScript(); }; class DLL_LOCAL ResourceObject: public QObject { Q_OBJECT private: MyNetworkAccessManager networkAccessManager; QUrl url; int loginTry; int progress; bool finished; bool signalPrint; MultiPageLoaderPrivate & multiPageLoader; public: ResourceObject(MultiPageLoaderPrivate & mpl, const QUrl & u, const settings::LoadPage & s); MyQWebPage webPage; LoaderObject lo; int httpErrorCode; const settings::LoadPage settings; public slots: void load(); void loadStarted(); void loadProgress(int progress); void loadFinished(bool ok); void waitWindowStatus(); void printRequested(QWebFrame * frame); void loadDone(); void handleAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator); void warning(const QString & str); void error(const QString & str); void sslErrors(QNetworkReply *reply, const QList &); void amfinished(QNetworkReply * reply); }; class DLL_LOCAL MyCookieJar: public QNetworkCookieJar { private: QList extraCookies; public: void clearExtraCookies(); void useCookie(const QUrl & url, const QString & name, const QString & value); QList cookiesForUrl(const QUrl & url) const; void loadFromFile(const QString & path); void saveToFile(const QString & path); }; class DLL_LOCAL MultiPageLoaderPrivate: public QObject { Q_OBJECT public: MyCookieJar * cookieJar; MultiPageLoader & outer; const settings::LoadGlobal settings; QList resources; int loading; int progressSum; bool isMainLoader; bool loadStartedEmitted; bool hasError; bool finishedEmitted; TempFile tempIn; int dpi; MultiPageLoaderPrivate(const settings::LoadGlobal & settings, int dpi, MultiPageLoader & o); ~MultiPageLoaderPrivate(); LoaderObject * addResource(const QUrl & url, const settings::LoadPage & settings); void load(); void clearResources(); void cancel(); public slots: void fail(); void loadDone(); }; } #include "dllend.inc" #endif //__MULTIPAGELOADER_P_HH__ wkhtmltopdf-0.12.5/src/lib/outline.cc000066400000000000000000000252061343154624600175020ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "outline_p.hh" #include #include using namespace std; #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ namespace wkhtmltopdf { /*! \file outline_p.hh \brief Defines the classes OutlinePrivate and OutlineItem */ /*! \class OutlineItem \brief Class describing an item in the outline */ OutlineItem::OutlineItem(): parent(NULL), page(-1), display(true), forwardLinks(false), backLinks(false) {} /*! \brief Recursivily delete the subtree */ OutlineItem::~OutlineItem() { foreach (OutlineItem * i, children) delete i; } void OutlineItem::fillAnchors(const OutlineItem * other, int & anchorCounter, QVector > & local, QHash & anchors) { if (!other || other->children.size() != children.size() || other->document != document || other->value != value || other->display != display) other=0; if (other) { anchor = other->anchor; tocAnchor = other->anchor; } else { anchor = QString("__WKANCHOR_")+QString::number(anchorCounter++,36); tocAnchor = QString("__WKANCHOR_")+QString::number(anchorCounter++,36); } if (forwardLinks) anchors[anchor] = element; if (backLinks) local.push_back( QPair(element, tocAnchor) ); for (int i=0; i < children.size(); ++i) children[i]->fillAnchors(other?other->children[i]:0, anchorCounter, local, anchors); } bool OutlineItem::differentFrom(const OutlineItem * other) const { if (other->children.size() != children.size() || other->page != page || other->document != document || other->value != value || other->display != display) return true; for (int i=0; i < children.size(); ++i) if (children[i]->differentFrom(other->children[i])) return true; return false; } /*! \class OutlinePrivate \brief Class providing implementation details of Outline */ OutlinePrivate::OutlinePrivate(const settings::PdfGlobal & s): settings(s), pageCount(0), anchorCounter(0) { } OutlinePrivate::~OutlinePrivate() { foreach (OutlineItem * i, documentOutlines) delete i; } void OutlinePrivate::fillChildAnchors(OutlineItem * item, QHash & anchors) { foreach (OutlineItem * i, item->children) { if (i->anchor.isEmpty()) continue; anchors[i->anchor] = i->element; fillChildAnchors(i, anchors); } } void OutlinePrivate::outlineChildren(OutlineItem * item, QPrinter * printer, int level) { if (level + 1 > settings.outlineDepth) return; foreach (OutlineItem * i, item->children) { printer->beginSectionOutline(i->value, i->anchor); outlineChildren(i, printer, level+1); printer->endSectionOutline(); } } QString escape(QString str) { return str.replace('&',"&") .replace('<',"<") .replace('>',">") .replace('"',""") .replace('\'',"'"); } void OutlinePrivate::dumpChildren(QTextStream & stream, const QList & items, int level) const { foreach (OutlineItem * item, items) { for (int i=0; i < level; ++i) stream << " "; stream << "value) << "\" page=\"" << (item->page + prefixSum[item->document]+ settings.pageOffset) << "\" link=\"" << escape(item->anchor) << "\" backLink=\"" << escape(item->tocAnchor) << "\""; if (item->children.empty()) stream << "/>" << endl; else { stream << ">" << endl; dumpChildren(stream, item->children, level+1); for (int i=0; i < level; ++i) stream << " "; stream << "" << endl; } } } void OutlinePrivate::buildPrefixSum() { prefixSum.clear(); prefixSum.push_back(0); foreach (int x, documentPages) prefixSum.push_back( prefixSum.back() + x); } void Outline::dump(QTextStream & stream) const { d->buildPrefixSum(); stream << "" << endl; stream << "" << endl; d->dumpChildren(stream, d->documentOutlines, 1); stream << "" << endl; } /*! \file outline.hh \brief Defines the Outline class */ /*! \class Outline \brief Class responsible for building and keeping an outline of a document. */ /*! \brief Construct a new outline class \param settings The settings to use */ Outline::Outline(const settings::PdfGlobal & settings): d(new OutlinePrivate(settings)) {} Outline::~Outline() {delete d;} /*! \brief Replace a webpage in the outline \param document The number of the webpage \param name The name of the webpage \param wp A webprinter for the page \param frame The frame containing the webpage */ bool Outline::replaceWebPage(int document, const QString & name, QWebPrinter & wp, QWebFrame * frame, const settings::PdfObject & ps, QVector > & local, QHash & anchors) { QMap< QPair >, QWebElement> headings; foreach (const QWebElement & e, frame->findAllElements("h1,h2,h3,h4,h5,h6,h7,h8,h9")) { QPair location = wp.elementLocation(e); headings[ qMakePair(location.first, qMakePair(location.second.y(), location.second.x()) ) ] = e; } //This heuristic is a little strange, it tries to create a real tree, //even though someone puts a h5 below a h1 or stuff like that //The way this is handled is having a level stack, indicating what h-tags //a level level in the tree currently represents QVector levelStack; levelStack.push_back(0); OutlineItem * root = new OutlineItem(); root->page = 0; root->document = document; root->value = name; root->display = true; OutlineItem * old = root; for (QMap< QPair >, QWebElement>::iterator i = headings.begin(); i != headings.end(); ++i) { const QWebElement & element = i.value(); uint level = element.tagName().mid(1).toInt(); QString value = element.toPlainText().replace("\n", " ").trimmed(); if (i.key().first == -1 || value == "") continue; OutlineItem * item = new OutlineItem(); item->page = i.key().first; item->document = document; item->value = value; item->element = element; item->forwardLinks = ps.toc.forwardLinks; item->backLinks = ps.toc.backLinks; while (levelStack.back() >= level) { old = old->parent; levelStack.pop_back(); } item->parent = old; old->children.push_back(item); old = item; levelStack.push_back(level); } root->fillAnchors(d->documentOutlines[document], d->anchorCounter, local, anchors); bool changed=d->documentOutlines[document]->differentFrom(root); delete d->documentOutlines[document]; d->documentOutlines[document] = root; if (d->documentPages[document] != wp.pageCount()) { d->pageCount -= d->documentPages[document]; d->documentPages[document] = wp.pageCount(); d->pageCount += d->documentPages[document]; changed=true; } return changed; } /*! \brief Add a new webpage to the outline \param name The name of the webpage \param wp A webprinter for the page \param frame The frame containing the webpage */ void Outline::addWebPage(const QString & name, QWebPrinter & wp, QWebFrame * frame, const settings::PdfObject & ps, QVector > & local, QHash & anchors) { Q_UNUSED(name); addEmptyWebPage(); replaceWebPage(d->documentOutlines.size()-1, name, wp, frame, ps, local, anchors); } void Outline::addEmptyWebPage() { OutlineItem * root = new OutlineItem(); root->page = 0; root->document = d->documentPages.size(); root->value = ""; root->display = true; d->documentOutlines.push_back(root); d->pageCount += 1; d->documentPages.push_back(1); } void OutlinePrivate::buildHFCache(OutlineItem * i, int level) { buildPrefixSum(); if (level >= hfCache.size()) return; foreach (OutlineItem * j, i->children) { int page = j->page + prefixSum[j->document]; while (hfCache[level].size() < page) hfCache[level].push_back(hfCache[level].back()); if (hfCache[level].size() == page) hfCache[level].push_back(j); buildHFCache(j, level+1); } } /*! \brief Fill in header footer parameters for a given page \param page The page to fill in for \param parms The structure to fill */ void Outline::fillHeaderFooterParms(int page, QHash & parms, const settings::PdfObject & ps) { //Build hfcache if (d->hfCache.size() == 0) { for (int i=0; i < 3; ++i) { QList< OutlineItem *> x; x.push_back(NULL); d->hfCache.push_back(x); } foreach (OutlineItem * i, d->documentOutlines) d->buildHFCache(i, 0); } for (int i=0; i < 3; ++i) while (d->hfCache[i].size() <= page) d->hfCache[i].push_back(d->hfCache[i].back()); int off = d->settings.pageOffset; typedef QPair SP; foreach (const SP & rep, ps.replacements) parms[rep.first] = rep.second; parms["frompage"] = QString::number(off+1); parms["topage"] = QString::number(off+d->pageCount); parms["page" ] = QString::number(page+off); parms["webpage"] = ps.page; parms["section" ] = d->hfCache[0][page]?d->hfCache[0][page]->value:QString(""); parms["subsection" ] = d->hfCache[1][page]?d->hfCache[1][page]->value:QString(""); parms["subsubsection" ] = d->hfCache[2][page]?d->hfCache[2][page]->value:QString(""); } /*! \brief Fill in anchor as to add to a given document \param doc The 0 indexed document number (in order of addWebPage) \param anchors The structure to fill */ void Outline::fillAnchors(int doc, QHash & anchors) { if (doc < 0 || doc >= d->documentOutlines.size()) return; d->fillChildAnchors( d->documentOutlines[doc], anchors ); } /*! \brief return the number of pages in the outlined document */ int Outline::pageCount() { return d->pageCount; } /*! \brief Print the document outline to a given printer \param printer The printer to print to */ void Outline::printOutline(QPrinter * printer) { if (!d->settings.outline) return; foreach (OutlineItem * i, d->documentOutlines) d->outlineChildren(i, printer, 0); } } #endif //__EXTENSIVE_WKHTMLTOPDF_QT_HACK__ wkhtmltopdf-0.12.5/src/lib/outline.hh000066400000000000000000000041051343154624600175070ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __OUTLINE_HH__ #define __OUTLINE_HH__ #include "pdfsettings.hh" #include #include #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ #include "dllbegin.inc" namespace wkhtmltopdf { class DLL_LOCAL OutlinePrivate; class DLL_LOCAL Outline { public: Outline(const settings::PdfGlobal & settings); ~Outline(); void addEmptyWebPage(); bool replaceWebPage(int d, const QString & name, QWebPrinter & wp, QWebFrame * f, const settings::PdfObject & ps, QVector > & local, QHash & anchors); void addWebPage(const QString & name, QWebPrinter & wp, QWebFrame * frame, const settings::PdfObject & ps, QVector > & local, QHash & external); void fillHeaderFooterParms(int page, QHash & parms, const settings::PdfObject & ps); void fillAnchors(int d, QHash & anchors); int pageCount(); void printOutline(QPrinter * printer); void dump(QTextStream & stream) const; private: OutlinePrivate * d; friend class TocPrinter; friend class TocPrinterPrivate; }; #include "dllend.inc" } #endif //__EXTENSIVE_WKHTMLTOPDF_QT_HACK__ #endif //__OUTLINE_HH__ wkhtmltopdf-0.12.5/src/lib/outline_p.hh000066400000000000000000000044221343154624600200300ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __OUTLINE_P_HH__ #define __OUTLINE_P_HH__ #include "outline.hh" #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ #include "dllbegin.inc" namespace wkhtmltopdf { class DLL_LOCAL OutlineItem { public: QList children; OutlineItem * parent; uint page; uint document; QString value; QWebElement element; QString anchor; QString tocAnchor; bool display; bool forwardLinks; bool backLinks; void fillAnchors(const OutlineItem * other, int & anchorCounter, QVector > & local, QHash & anchors); bool differentFrom(const OutlineItem * other) const; OutlineItem(); ~OutlineItem(); }; class DLL_LOCAL OutlinePrivate { public: const settings::PdfGlobal & settings; QList documentOutlines; QList documentPages; QList prefixSum; int pageCount; int anchorCounter; QList< QList< OutlineItem *> > hfCache; OutlinePrivate(const settings::PdfGlobal & settings); ~OutlinePrivate(); void buildPrefixSum(); void fillChildAnchors(OutlineItem * item, QHash & anchors); void outlineChildren(OutlineItem * item, QPrinter * printer, int level); void buildHFCache(OutlineItem * i, int level); void dumpChildren(QTextStream & stream, const QList & items, int level) const; }; #include "dllend.inc" } #endif //__EXTENSIVE_WKHTMLTOPDF_QT_HACK__ #endif //__OUTLINE_P_HH__ wkhtmltopdf-0.12.5/src/lib/pdf.h000066400000000000000000000102541343154624600164330ustar00rootroot00000000000000/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- * vi:set ts=4 sts=4 sw=4 noet : * * Copyright 2010 wkhtmltopdf authors * * This file is part of wkhtmltopdf. * * wkhtmltopdf is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * wkhtmltopdf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with wkhtmltopdf. If not, see . */ #ifndef __PDF_H__ #define __PDF_H__ #ifdef BUILDING_WKHTMLTOX #include "dllbegin.inc" #else #include #endif struct wkhtmltopdf_global_settings; typedef struct wkhtmltopdf_global_settings wkhtmltopdf_global_settings; struct wkhtmltopdf_object_settings; typedef struct wkhtmltopdf_object_settings wkhtmltopdf_object_settings; struct wkhtmltopdf_converter; typedef struct wkhtmltopdf_converter wkhtmltopdf_converter; typedef void (*wkhtmltopdf_str_callback)(wkhtmltopdf_converter * converter, const char * str); typedef void (*wkhtmltopdf_int_callback)(wkhtmltopdf_converter * converter, const int val); typedef void (*wkhtmltopdf_void_callback)(wkhtmltopdf_converter * converter); CAPI(int) wkhtmltopdf_init(int use_graphics); CAPI(int) wkhtmltopdf_deinit(); CAPI(int) wkhtmltopdf_extended_qt(); CAPI(const char *) wkhtmltopdf_version(); CAPI(wkhtmltopdf_global_settings *) wkhtmltopdf_create_global_settings(); CAPI(void) wkhtmltopdf_destroy_global_settings(wkhtmltopdf_global_settings *); CAPI(wkhtmltopdf_object_settings *) wkhtmltopdf_create_object_settings(); CAPI(void) wkhtmltopdf_destroy_object_settings(wkhtmltopdf_object_settings *); CAPI(int) wkhtmltopdf_set_global_setting(wkhtmltopdf_global_settings * settings, const char * name, const char * value); CAPI(int) wkhtmltopdf_get_global_setting(wkhtmltopdf_global_settings * settings, const char * name, char * value, int vs); CAPI(int) wkhtmltopdf_set_object_setting(wkhtmltopdf_object_settings * settings, const char * name, const char * value); CAPI(int) wkhtmltopdf_get_object_setting(wkhtmltopdf_object_settings * settings, const char * name, char * value, int vs); CAPI(wkhtmltopdf_converter *) wkhtmltopdf_create_converter(wkhtmltopdf_global_settings * settings); CAPI(void) wkhtmltopdf_destroy_converter(wkhtmltopdf_converter * converter); CAPI(void) wkhtmltopdf_set_warning_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_str_callback cb); CAPI(void) wkhtmltopdf_set_error_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_str_callback cb); CAPI(void) wkhtmltopdf_set_phase_changed_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_void_callback cb); CAPI(void) wkhtmltopdf_set_progress_changed_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_int_callback cb); CAPI(void) wkhtmltopdf_set_finished_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_int_callback cb); /* CAPI(void) wkhtmltopdf_begin_conversion(wkhtmltopdf_converter * converter); */ /* CAPI(void) wkhtmltopdf_cancel(wkhtmltopdf_converter * converter); */ CAPI(int) wkhtmltopdf_convert(wkhtmltopdf_converter * converter); CAPI(void) wkhtmltopdf_add_object( wkhtmltopdf_converter * converter, wkhtmltopdf_object_settings * setting, const char * data); CAPI(int) wkhtmltopdf_current_phase(wkhtmltopdf_converter * converter); CAPI(int) wkhtmltopdf_phase_count(wkhtmltopdf_converter * converter); CAPI(const char *) wkhtmltopdf_phase_description(wkhtmltopdf_converter * converter, int phase); CAPI(const char *) wkhtmltopdf_progress_string(wkhtmltopdf_converter * converter); CAPI(int) wkhtmltopdf_http_error_code(wkhtmltopdf_converter * converter); CAPI(long) wkhtmltopdf_get_output(wkhtmltopdf_converter * converter, const unsigned char **); #ifdef BUILDING_WKHTMLTOX #include "dllend.inc" #else #include #endif #endif /*__PDF_H__*/ wkhtmltopdf-0.12.5/src/lib/pdf_c_bindings.cc000066400000000000000000000715101343154624600207520ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . /** * \file pdf.h * \brief Provides C bindings for pdf conversion */ #include "pdf_c_bindings_p.hh" #include "utilities.hh" #include #include #include #include "dllbegin.inc" /** * \page pagesettings Setting * Settings can be supplied to PDF and image c-bindings using utf-8 encoded strings. * This is done by relatively simple reflection on the CropSettings, HeaderFooter, Margin, * ImageGlobal, PdfGlobal, PdfObject, Size, and TableOfContent classes. * * - The \ref wkhtmltopdf_global_settings corresponds to the PdfGlobal class and is documented in \ref pagePdfGlobal. * - The \ref wkhtmltopdf_object_settings corresponds to the PdfGlobal class and is documented in \ref pagePdfObject. * - The \ref wkhtmltopdf_image_settings corresponds to the ImageGlobal class and is documented in \ref pageImageGlobal. * * \section pageWeb Web page specific settings * The following web page specific settings apply * - \b web.background Should we print the background? Must be either "true" or "false". * - \b web.loadImages Should we load images? Must be either "true" or "false". * - \b web.enableJavascript Should we enable javascript? Must be either "true" or "false". * - \b web.enableIntelligentShrinking Should we enable intelligent shrinkng to fit more content * on one page? Must be either "true" or "false". Has no effect for wkhtmltoimage. * - \b web.minimumFontSize The minimum font size allowed. E.g. "9" * - \b web.printMediaType Should the content be printed using the print media type instead * of the screen media type. Must be either "true" or "false". Has no effect for wkhtmltoimage. * - \b web.defaultEncoding What encoding should we guess content is using if they do not * specify it properly? E.g. "utf-8" * - \b web.userStyleSheet Url er path to a user specified style sheet. * - \b web.enablePlugins Should we enable NS plugins, must be either "true" or "false". * Enabling this will have limited success. * * \section pageLoad Object Specific loading settings * The following settings apply for object loading. * - \b load.username The user name to use when loging into a website, E.g. "bart" * - \b load.password The password to used when logging into a website, E.g. "elbarto" * - \b load.jsdelay The mount of time in milliseconds to wait after a page has done loading until * it is actually printed. E.g. "1200". We will wait this amount of time or until, javascript * calls window.print(). * - \b load.zoomFactor How much should we zoom in on the content? E.g. "2.2". * - \b load.customHeaders TODO * - \b load.repertCustomHeaders Should the custom headers be sent all elements loaded instead of * only the main page? Must be either "true" or "false". * - \b load.cookies TODO * - \b load.post TODO * - \b load.blockLocalFileAccess Disallow local and piped files to access other local files. Must * be either "true" or "false". * - \b load.stopSlowScript Stop slow running javascript. Must be either "true" or "false". * - \b load.debugJavascript Forward javascript warnings and errors to the warning callback. * Must be either "true" or "false". * - \b load.loadErrorHandling How should we handle obejcts that fail to load. Must be one of: * - "abort" Abort the conversion process * - "skip" Do not add the object to the final output * - "ignore" Try to add the object to the final output. * - \b load.proxy String describing what proxy to use when loading the object. * - \b load.runScript TODO * * \section pageHeaderFooter Header and footer settings * The same settings can be applied for headers and footers, here there are explained in * terms of the header. * - \b header.fontSize The font size to use for the header, e.g. "13" * - \b header.fontName The name of the font to use for the header. e.g. "times" * - \b header.left The string to print in the left part of the header, note that some sequences * are replaced in this string, see the wkhtmltopdf manual. * - \b header.center The text to print in the center part of the header. * - \b header.right The text to print in the right part of the header. * - \b header.line Whether a line should be printed under the header (either "true" or "false"). * - \b header.spacing The amount of space to put between the header and the content, e.g. "1.8". Be * aware that if this is too large the header will be printed outside the pdf document. This * can be corrected with the margin.top setting. * - \b header.htmlUrl Url for a HTML document to use for the header. * * \section pagePdfGlobal Pdf global settings * The \ref wkhtmltopdf_global_settings structure contains the following settings: * - \b size.pageSize The paper size of the output document, e.g. "A4". * - \b size.width The with of the output document, e.g. "4cm". * - \b size.height The height of the output document, e.g. "12in". * - \b orientation The orientation of the output document, must be either "Landscape" or "Portrait". * - \b colorMode Should the output be printed in color or gray scale, must be either "Color" or "Grayscale" * - \b resolution Most likely has no effect. * - \b dpi What dpi should we use when printing, e.g. "80". * - \b pageOffset A number that is added to all page numbers when printing headers, footers and table of content. * - \b copies How many copies should we print?. e.g. "2". * - \b collate Should the copies be collated? Must be either "true" or "false". * - \b outline Should a outline (table of content in the sidebar) be generated and put into the PDF? Must be either "true" or false". * - \b outlineDepth The maximal depth of the outline, e.g. "4". * - \b dumpOutline If not set to the empty string a XML representation of the outline is dumped to this file. * - \b out The path of the output file, if "-" output is sent to stdout, if empty the output is stored in a buffer. * - \b documentTitle The title of the PDF document. * - \b useCompression Should we use loss less compression when creating the pdf file? Must be either "true" or "false". * - \b margin.top Size of the top margin, e.g. "2cm" * - \b margin.bottom Size of the bottom margin, e.g. "2cm" * - \b margin.left Size of the left margin, e.g. "2cm" * - \b margin.right Size of the right margin, e.g. "2cm" * - \b imageDPI The maximal DPI to use for images in the pdf document. * - \b imageQuality The jpeg compression factor to use when producing the pdf document, e.g. "92". * - \b load.cookieJar Path of file used to load and store cookies. * * \section pagePdfObject Pdf object settings * The \ref wkhtmltopdf_object_settings structure contains the following settings: * - \b toc.useDottedLines Should we use a dotted line when creating a table of content? * Must be either "true" or "false". * - \b toc.captionText The caption to use when creating a table of content. * - \b toc.forwardLinks Should we create links from the table of content into the actual content? * Must be either "true or "false. * - \b toc.backLinks Should we link back from the content to this table of content. * - \b toc.indentation The indentation used for every table of content level, e.g. "2em". * - \b toc.fontScale How much should we scale down the font for every toc level? E.g. "0.8" * - \b page The URL or path of the web page to convert, if "-" input is read from stdin. * - \b header.* Header specific settings see \ref pageHeaderFooter. * - \b footer.* Footer specific settings see \ref pageHeaderFooter. * - \b useExternalLinks Should external links in the HTML document be converted into * external pdf links? Must be either "true" or "false. * - \b useLocalLinks Should internal links in the HTML document be converted into pdf * references? Must be either "true" or "false" * - \b replacements TODO * - \b produceForms Should we turn HTML forms into PDF forms? Must be either "true" or file". * - \b load.* Page specific settings related to loading content, see \ref pageLoad. * - \b web.* See \ref pageWeb. * - \b includeInOutline Should the sections from this document be included in the outline and table of content? * - \b pagesCount Should we count the pages of this document, in the counter used for TOC, headers and footers? * - \b tocXsl If not empty this object is a table of content object, "page" is ignored and this xsl style * sheet is used to convert the outline XML into a table of content. */ /** * \struct wkhtmltopdf_global_settings * \brief A struct holding global settings * * See also \ref pagePdfGlobal */ /** * \struct wkhtmltopdf_object_settings * \brief A struct holding object settings * * See also \ref pagePdfObject */ /** * \struct wkhtmltopdf_converter * \brief A struct holding information related to a conversion process */ /** * \typedef wkhtmltopdf_str_callback * \brief Function pointer type used for the error and warning callbacks * * \param converter The converter that issued the callback * \param str A utf8 encoded string containing the error or warning message. * * \sa wkhtmltopdf_set_error_callback, wkhtmltopdf_set_warning_callback */ /** * \typedef wkhtmltopdf_int_callback * \brief Function pointer type used for the progress_changed and finished callbacks * * For the progress_changed callback the value indicated the progress * within the current phase in percent. For the finished callback the value * if 1 if the conversion has successful and 0 otherwise. * * \param converter The converter that issued the callback * \param val The integer value * * \sa wkhtmltopdf_set_progress_changed, wkhtmltopdf_set_finished_callback */ /** * \typedef wkhtmltopdf_void_callback * \brief Function pointer type used for the phase_changed callback * * \param converter The converter that issued the callback * * \sa wkhtmltopdf_set_phase_changed_callback */ using namespace wkhtmltopdf; QApplication * a = 0; int usage = 0; void MyPdfConverter::warning(const QString & message) { if (warning_cb && globalSettings->logLevel > settings::Error) (warning_cb)(reinterpret_cast(this), message.toUtf8().constData()); } void MyPdfConverter::error(const QString & message) { if (error_cb && globalSettings->logLevel > settings::None) (error_cb)(reinterpret_cast(this), message.toUtf8().constData()); } void MyPdfConverter::phaseChanged() { if (phase_changed) (phase_changed)(reinterpret_cast(this)); } void MyPdfConverter::progressChanged(int progress) { if (progress_changed) (progress_changed)(reinterpret_cast(this), progress); } void MyPdfConverter::finished(bool ok) { if (finished_cb) (finished_cb)(reinterpret_cast(this), ok); } MyPdfConverter::MyPdfConverter(settings::PdfGlobal * gs): warning_cb(0), error_cb(0), phase_changed(0), progress_changed(0), finished_cb(0), converter(*gs), globalSettings(gs) { connect(&converter, SIGNAL(warning(const QString &)), this, SLOT(warning(const QString &))); connect(&converter, SIGNAL(error(const QString &)), this, SLOT(error(const QString &))); connect(&converter, SIGNAL(phaseChanged()), this, SLOT(phaseChanged())); connect(&converter, SIGNAL(progressChanged(int)), this, SLOT(progressChanged(int))); connect(&converter, SIGNAL(finished(bool)), this, SLOT(finished(bool))); } MyPdfConverter::~MyPdfConverter() { delete globalSettings; for (size_t i=0; i < objectSettings.size(); ++i) delete objectSettings[i]; objectSettings.clear(); } /** * \brief Check if the library is build against the wkhtmltopdf version of QT * * \return 1 if the library was build against the wkhtmltopdf version of QT and 0 otherwise */ CAPI(int) wkhtmltopdf_extended_qt() { #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ return 1; #else return 0; #endif } #define STRINGIZEE(a) # a #define STRINGIZE(a) STRINGIZEE(a) /** * \brief Return the version of wkhtmltopdf * Example: 0.12.1-development. The string is utf8 encoded and is owned by wkhtmltopdf. * * \return Qt version */ CAPI(const char *) wkhtmltopdf_version() { return STRINGIZE(FULL_VERSION); } /** * \brief Setup wkhtmltopdf * * Must be called before any other functions. * * \param use_graphics Should we use a graphics system * \returns 1 on success and 0 otherwise * * \sa wkhtmltopdf_deinit */ CAPI(int) wkhtmltopdf_init(int use_graphics) { ++usage; if (qApp == 0) { char x[256]; strcpy(x, "wkhtmltox"); char * arg[] = {x, 0}; int aa = 1; #if QT_VERSION >= 0x050000 && defined(Q_OS_UNIX) && !defined(__EXTENSIVE_WKHTMLTOPDF_QT_HACK__) setenv("QT_QPA_PLATFORM", "offscreen", 0); #endif bool ug = true; #if defined(Q_OS_UNIX) || defined(Q_OS_MAC) #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ ug = use_graphics; if (!ug) QApplication::setGraphicsSystem("raster"); #else Q_UNUSED(use_graphics); #endif #else Q_UNUSED(use_graphics); #endif a = new QApplication(aa, arg, ug); a->setApplicationName(x); MyLooksStyle * style = new MyLooksStyle(); a->setStyle(style); } return 1; } /** * \brief Deinit wkhtmltopdf * * Free up resources used by wkhtmltopdf, when this has been called no other * wkhtmltopdf function can be called. * * \returns 1 on success and 0 otherwise * * \sa wkhtmltopdf_init */ CAPI(int) wkhtmltopdf_deinit() { --usage; if (usage != 0) return 1; if (a != 0) delete a; return 1; } /** * \brief Create a new global settings object for pdf conversion * * Create a new global settings object for pdf conversion, settings can be altered with * \ref wkhtmltopdf_set_global_setting, and inspected with \ref wkhtmltopdf_get_global_setting. * Once the desired settings have been set a converter object can be created using \reg wkhtmltopdf_create_converter. * * \returns A wkhtmltopdf global settings object */ CAPI(wkhtmltopdf_global_settings *) wkhtmltopdf_create_global_settings() { return reinterpret_cast(new settings::PdfGlobal()); } /** * \brief Destroy a global settings object * * Normally one would not need to call this since ownership of the * settings object is transfarred to the converter. */ CAPI(void) wkhtmltopdf_destroy_global_settings(wkhtmltopdf_global_settings * obj) { delete reinterpret_cast(obj); } /** * \brief Alter a setting in a global settings object * * \sa \ref pagePdfGlobal, wkhtmltopdf_create_global_settings, wkhtmltopdf_get_global_setting * * \param settings The settings object to change * \param name The name of the setting * \param value The new value for the setting (encoded in UTF-8) * \returns 1 if the setting was updated successfully and 0 otherwise. */ CAPI(int) wkhtmltopdf_set_global_setting(wkhtmltopdf_global_settings * settings, const char * name, const char * value) { return reinterpret_cast(settings)->set(name, QString::fromUtf8(value)); } /** * \brief Retrieve a setting in a global settings object * * \sa \ref pagesettings, wkhtmltopdf_create_global_settings, wkhtmltopdf_set_global_setting * * \param settings The settings object to inspect * \param name The name of the setting to read * \param value A buffer of length at least \a vs, where the value (encoded in UTF-8) is stored. * \param vs The length of \a value * \returns 1 If the the setting exists and was read successfully and 0 otherwise */ CAPI(int) wkhtmltopdf_get_global_setting(wkhtmltopdf_global_settings * settings, const char * name, char * value, int vs) { QString res = reinterpret_cast(settings)->get(name); if (res.isNull()) return 0; qstrncpy(value, res.toUtf8().constData(), vs); return 1; } /** * \brief Create an object used to store object settings * * Create a new Object settings object for pdf conversion, settings can be altered with * \ref wkhtmltopdf_set_object_setting, and inspected with \ref wkhtmltopdf_get_object_setting. * Once the desired settings have been set the object can be added to a converter * by calling wkhtmltopdf_add_resource. * * \returns an object settings instance */ CAPI(wkhtmltopdf_object_settings *) wkhtmltopdf_create_object_settings() { return reinterpret_cast(new settings::PdfObject()); } /** * \brief Destroy a global settings object * * Normally one would not need to call this since ownership of the * settings object is transfarred to the converter. */ CAPI(void) wkhtmltopdf_destroy_object_settings(wkhtmltopdf_object_settings * obj) { delete reinterpret_cast(obj); } /** * \brief Alter a setting in a object settings object * * \sa \ref pagesettings, wkhtmltopdf_create_object_settings, wkhtmltopdf_get_object_setting * * \param settings The settings object to change * \param name The name of the setting * \param value The new value for the setting (encoded in UTF-8) * \returns 1 if the setting was updated successfully and 0 otherwise. */ CAPI(int) wkhtmltopdf_set_object_setting(wkhtmltopdf_object_settings * settings, const char * name, const char * value) { return reinterpret_cast(settings)->set(name, QString::fromUtf8(value)); } /** * \brief Retrieve a setting in a object settings object * * \sa \ref pagesettings, wkhtmltopdf_create_global_settings, wkhtmltopdf_set_global_setting * * \param settings The settings object to inspect * \param name The name of the setting to read * \param value A buffer of length at least \a vs, where the value is stored (encoded in UTF-8). * \param vs The length of \a value * \returns 1 If the the setting exists and was read successfully and 0 otherwise */ CAPI(int) wkhtmltopdf_get_object_setting(wkhtmltopdf_object_settings * settings, const char * name, char * value, int vs) { QString res = reinterpret_cast(settings)->get(name); if (res.isNull()) return 0; qstrncpy(value, res.toUtf8().constData(), vs); return 1; } /** * \brief Create a wkhtmltopdf converter object * * The converter object is used to convert one or more objects(web sides) into a single pdf. * Once a settings object has been parsed, it may no longer be accessed, and will eventually be freed. * The returned converter object must be freed by calling \ref wkhtmltopdf_destroy_converter * * \param settings The global settings to use during conversion. * \returns A wkhtmltopdf converter object */ CAPI(wkhtmltopdf_converter *) wkhtmltopdf_create_converter(wkhtmltopdf_global_settings * settings) { return reinterpret_cast( new MyPdfConverter(reinterpret_cast(settings))); } /** * \brief Destroy a wkhtmltopdf converter object * * An object must be destroyed to free up its memory, once it has been destroyed it may no longer * be accessed. * * \param settings The converter object to destroy */ CAPI(void) wkhtmltopdf_destroy_converter(wkhtmltopdf_converter * converter) { reinterpret_cast(converter)->deleteLater(); } /** * \brief Set the function that should be called when an warning message is issued during conversion * * \param converter The converter object on which warnings we want the callback to be called * \param cb The function to call when warning message is issued * */ CAPI(void) wkhtmltopdf_set_warning_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_str_callback cb) { reinterpret_cast(converter)->warning_cb = cb; } /** * \brief Set the function that should be called when an errors occurs during conversion * * \param converter The converter object on which errors we want the callback to be called * \param cb The function to call when an error occurs */ CAPI(void) wkhtmltopdf_set_error_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_str_callback cb) { reinterpret_cast(converter)->error_cb = cb; } /** * \brief Set the function that should be called whenever conversion changes phase * * The number of the new phase can be found by calling \ref wkhtmltopdf_current_phase * * \param converter The converter which phase change events to call back from * \param cb The function to call when phases change * * \sa wkhtmltopdf_current_phase, wkhtmltopdf_phase_count, wkhtmltopdf_phase_description */ CAPI(void) wkhtmltopdf_set_phase_changed_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_void_callback cb) { reinterpret_cast(converter)->phase_changed = cb; } /** * \brief Set the function that should be called when progress have been done during conversion. * * The progress in percent within the current phase is given as an integer to the callback function. * * \param converter The converter which progress events to call back from * \param cb The function to call when progress has occurred. * * \sa wkhtmltopdf_progress_description */ CAPI(void) wkhtmltopdf_set_progress_changed_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_int_callback cb) { reinterpret_cast(converter)->progress_changed = cb; } /** * \brief Set the function that should be called once the conversion has finished. * * \param converter The converter which finish events to call back from * \param cb The function to call when the conversion has finished has occurred. * * \sa wkhtmltopdf_convert */ CAPI(void) wkhtmltopdf_set_finished_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_int_callback cb) { reinterpret_cast(converter)->finished_cb = cb; } //CAPI(void) wkhtmltopdf_begin_conversion(wkhtmltopdf_converter * converter) { // reinterpret_cast(converter)->converter.beginConversion(); //} /** * \brief Convert the input objects into a pdf document * * This is the main method for the conversion process, during conversion progress information * warning, and errors are reported using the supplied call backs. Once the conversion is done * the output pdf (or ps) file will be placed at the location of the "out" setting supplied in * the global settings object during construction of the converter. If this setting is not supplied * or set to the empty string, the output can be retrieved using the \ref wkhtmltopdf_get_output * function. * * \paragm converter The converter to perform the conversion on. * * \returns 1 on success and 0 otherwise */ CAPI(int) wkhtmltopdf_convert(wkhtmltopdf_converter * converter) { return reinterpret_cast(converter)->converter.convert(); } //CAPI(void) wkhtmltopdf_cancel(wkhtmltopdf_converter * converter) { // reinterpret_cast(converter)->converter.cancel(); //} /** * \brief add an object (web page to convert) * * Add the object described by the supplied object settings to the list of objects (web pages to convert), * objects are placed in the output pdf in the order of addition. Once the object has been added, the * supplied settings may no longer be accessed, it Wit eventually be freed by wkhtmltopdf. * If a none NULL and none empty utf8 encoded string is supplied to data, this HTML content will be converted * instead of the content located at "page" setting of the supplied object settings instance. * * \param converter The converter to add the object to * \param settings The setting describing the object to add * \param data HTML content of the object to convert (encoded in UTF-8) or NULL */ CAPI(void) wkhtmltopdf_add_object(wkhtmltopdf_converter * converter, wkhtmltopdf_object_settings * settings, const char * data) { QString str= QString::fromUtf8(data); reinterpret_cast(converter)->converter.addResource( *reinterpret_cast(settings), &str); reinterpret_cast(converter)->objectSettings.push_back(reinterpret_cast(settings)); } /** * \brief Get the number of the current conversion phase * * Conversion is done in a number of named phases, this * function will retrieve the number of the current conversion phase, * which will be a number between 0 and wkhtmltopdf_phase_count(converter)-1. * * The description (name) of any phase can be retrieved by calling the * \ref wkhtmltopdf_phase_description method. * * \param converter The converter to find the current phase of * \returns The current phase of the supplied converter */ CAPI(int) wkhtmltopdf_current_phase(wkhtmltopdf_converter * converter) { return reinterpret_cast(converter)->converter.currentPhase(); } /** * \brief Get the total number of phases the conversion process will go trough * * \param converter The converter to query * \returns The total number of phases in the conversion process * * \sa wkhtmltopdf_current_phase, wkhtmltopdf_phase_description */ CAPI(int) wkhtmltopdf_phase_count(wkhtmltopdf_converter * converter) { return reinterpret_cast(converter)->converter.phaseCount(); } /** * \brief Return a short utf8 description of a conversion phase * * \param converter The converter to query * \param phase The number of the conversion step of which we want a description * \returns A description of the conversion phase * * \sa wkhtmltopdf_current_phase, wkhtmltopdf_phase_description */ CAPI(const char *) wkhtmltopdf_phase_description(wkhtmltopdf_converter * converter, int phase) { MyPdfConverter* conv = reinterpret_cast(converter); QString pd = conv->converter.phaseDescription(phase); if (!conv->utf8StringCache.contains(pd)) { return conv->utf8StringCache.insert(pd, pd.toUtf8()).value().constData(); } else return conv->utf8StringCache[pd].constData(); } /** * \brief Return a short utf8 string indicating progress within a phase * * Will typically return a string like "40%" * * \param converter The converter to query * \returns A string containing a progress indication * * \sa wkhtmltopdf_set_progress_changed_callback */ CAPI(const char *) wkhtmltopdf_progress_string(wkhtmltopdf_converter * converter) { MyPdfConverter* conv = reinterpret_cast(converter); QString ps = conv->converter.progressString(); if (!conv->utf8StringCache.contains(ps)) return conv->utf8StringCache.insert(ps, ps.toUtf8()).value().constData(); else return conv->utf8StringCache[ps].constData(); } /** * \brief Return the largest HTTP error code encountered during conversion * * Return the largest HTTP code greater then or equal to 300 encountered during loading * of any of the supplied objects, if no such error code is found 0 is returned. * This function will only return a useful result after \ref wkhtmltopdf_convert has been called. * * \param converter The converter to query * \returns The HTTP error code. */ CAPI(int) wkhtmltopdf_http_error_code(wkhtmltopdf_converter * converter) { return reinterpret_cast(converter)->converter.httpErrorCode(); } /** * \brief Get the output document generated during conversion. * * If no "out" location was specified in the global settings object, the binary * output (pdf document) of the convection process will be stored in a buffer. * * \param converter The converter to query * \param d A pointer to a pointer that will be made to point to the output data * \returns The length of the output data */ CAPI(long) wkhtmltopdf_get_output(wkhtmltopdf_converter * converter, const unsigned char ** d) { const QByteArray & out = reinterpret_cast(converter)->converter.output(); *d = (const unsigned char*)out.constData(); return out.size(); } // LocalWords: eval progn stroustrup innamespace sts sw noet wkhtmltopdf DLL // LocalWords: ifdef WKHTMLTOX UNDEF undef endif pdf dllbegin namespace const // LocalWords: QString cb bool ok globalSettings phaseChanged progressChanged // LocalWords: objectSettings utf CropSettings HeaderFooter ImageGlobal dpi sa // LocalWords: PdfGlobal PdfObject TableOfContent pagePdfGlobal pagePdfObject // LocalWords: pageImageGlobal pageGlobalLoad pageSize colorMode Grayscale // LocalWords: pageOffset outlineDepth dumpOutline stdout pageLoad pageWeb aa // LocalWords: includeInOutline pagesCount tocXsl xsl struct typedef str CAPI // LocalWords: param STRINGIZEE STRINGIZE deinit qApp strcpy wkhtmltox arg ug // LocalWords: WS MACX MyLooksStyle setStyle isNull qstrncpy MyPdfConverter // LocalWords: beginConversion beginConvertion paragm addResource // LocalWords: currentPhase phaseCount urrent http httpErrorCode QByteArray // LocalWords: constData wkhtmltopdf-0.12.5/src/lib/pdf_c_bindings_p.hh000066400000000000000000000036301343154624600213010ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __PDF_C_BINDINGS_P_HH__ #define __PDF_C_BINDINGS_P_HH__ #include "pdf.h" #include "pdfconverter.hh" #include #include #include #include "dllbegin.inc" class DLL_LOCAL MyPdfConverter: public QObject { Q_OBJECT public: wkhtmltopdf_str_callback warning_cb; wkhtmltopdf_str_callback error_cb; wkhtmltopdf_void_callback phase_changed; wkhtmltopdf_int_callback progress_changed; wkhtmltopdf_int_callback finished_cb; wkhtmltopdf::PdfConverter converter; wkhtmltopdf::settings::PdfGlobal * globalSettings; std::vector objectSettings; QHash utf8StringCache; MyPdfConverter(wkhtmltopdf::settings::PdfGlobal * gs); ~MyPdfConverter(); public slots: void warning(const QString & message); void error(const QString & message); void phaseChanged(); void progressChanged(int progress); void finished(bool ok); private: MyPdfConverter(const MyPdfConverter&); }; #include "dllend.inc" #endif //__PDF_C_BINDINGS_P_HH__ wkhtmltopdf-0.12.5/src/lib/pdfconverter.cc000066400000000000000000001131631343154624600205240ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "pdfconverter_p.hh" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN32 #include #include #endif #include "dllbegin.inc" using namespace wkhtmltopdf; using namespace wkhtmltopdf::settings; #define STRINGIZE_(x) #x #define STRINGIZE(x) STRINGIZE_(x) const qreal PdfConverter::millimeterToPointMultiplier = 2.83464567; DLL_LOCAL QMap PageObject::webPageToObject; struct DLL_LOCAL StreamDumper { QFile out; QTextStream stream; StreamDumper(const QString & path): out(path), stream(&out) { out.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text); stream.setCodec("UTF-8"); } }; /*! \file pageconverter.hh \brief Defines the PdfConverter class */ /*! \file pageconverter_p.hh \brief Defines the PdfConverterPrivate class */ bool DLL_LOCAL looksLikeHtmlAndNotAUrl(QString str) { QString s = str.split("?")[0]; return s.count('<') > 0 || str.startsWith("data:", Qt::CaseInsensitive); } PdfConverterPrivate::PdfConverterPrivate(PdfGlobal & s, PdfConverter & o) : settings(s), pageLoader(s.load, settings.dpi, true), out(o), printer(0), painter(0) #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ , measuringHFLoader(s.load, settings.dpi), hfLoader(s.load, settings.dpi), tocLoader1(s.load, settings.dpi), tocLoader2(s.load, settings.dpi) , tocLoader(&tocLoader1), tocLoaderOld(&tocLoader2) , outline(0), currentHeader(0), currentFooter(0) #endif { #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ phaseDescriptions.push_back("Loading pages"); phaseDescriptions.push_back("Counting pages"); phaseDescriptions.push_back("Loading TOC"); phaseDescriptions.push_back("Resolving links"); phaseDescriptions.push_back("Loading headers and footers"); #else phaseDescriptions.push_back("Loading page"); #endif phaseDescriptions.push_back("Printing pages"); phaseDescriptions.push_back("Done"); connect(&pageLoader, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int))); connect(&pageLoader, SIGNAL(loadFinished(bool)), this, SLOT(pagesLoaded(bool))); connect(&pageLoader, SIGNAL(error(QString)), this, SLOT(forwardError(QString))); connect(&pageLoader, SIGNAL(warning(QString)), this, SLOT(forwardWarning(QString))); #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ connect(&measuringHFLoader, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int))); connect(&measuringHFLoader, SIGNAL(loadFinished(bool)), this, SLOT(measuringHeadersLoaded(bool))); connect(&measuringHFLoader, SIGNAL(error(QString)), this, SLOT(forwardError(QString))); connect(&measuringHFLoader, SIGNAL(warning(QString)), this, SLOT(forwardWarning(QString))); connect(&hfLoader, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int))); connect(&hfLoader, SIGNAL(loadFinished(bool)), this, SLOT(headersLoaded(bool))); connect(&hfLoader, SIGNAL(error(QString)), this, SLOT(forwardError(QString))); connect(&hfLoader, SIGNAL(warning(QString)), this, SLOT(forwardWarning(QString))); connect(&tocLoader1, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int))); connect(&tocLoader1, SIGNAL(loadFinished(bool)), this, SLOT(tocLoaded(bool))); connect(&tocLoader1, SIGNAL(error(QString)), this, SLOT(forwardError(QString))); connect(&tocLoader1, SIGNAL(warning(QString)), this, SLOT(forwardWarning(QString))); connect(&tocLoader2, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int))); connect(&tocLoader2, SIGNAL(loadFinished(bool)), this, SLOT(tocLoaded(bool))); connect(&tocLoader2, SIGNAL(error(QString)), this, SLOT(forwardError(QString))); connect(&tocLoader2, SIGNAL(warning(QString)), this, SLOT(forwardWarning(QString))); #endif if ( ! settings.viewportSize.isEmpty()) { QStringList viewportSizeList = settings.viewportSize.split("x"); int width = viewportSizeList.first().toInt(); int height = viewportSizeList.last().toInt(); viewportSize = QSize(width,height); } } PdfConverterPrivate::~PdfConverterPrivate() { clearResources(); } void PdfConverterPrivate::beginConvert() { error=false; progressString = "0%"; currentPhase=0; errorCode=0; #ifndef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ if (objects.size() > 1) { emit out.error("This version of wkhtmltopdf is build against an unpatched version of QT, and does not support more then one input document."); fail(); return; } #else bool headerHeightsCalcNeeded = false; #endif for (QList::iterator i=objects.begin(); i != objects.end(); ++i) { PageObject & o=*i; settings::PdfObject & s = o.settings; #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ if (!s.header.htmlUrl.isEmpty() ) { if (looksLikeHtmlAndNotAUrl(s.header.htmlUrl)) { emit out.error("--header-html should be a URL and not a string containing HTML code."); fail(); return; } // we should auto calculate header if top margin is not specified if (settings.margin.top.first == -1) { headerHeightsCalcNeeded = true; o.measuringHeader = &measuringHFLoader.addResource( MultiPageLoader::guessUrlFromString(s.header.htmlUrl), s.load)->page; } else { // or just set static values // add spacing to prevent moving header out of page o.headerReserveHeight = settings.margin.top.first + s.header.spacing; } } if (!s.footer.htmlUrl.isEmpty()) { if (looksLikeHtmlAndNotAUrl(s.footer.htmlUrl)) { emit out.error("--footer-html should be a URL and not a string containing HTML code."); fail(); return; } if (settings.margin.bottom.first == -1) { // we should auto calculate footer if top margin is not specified headerHeightsCalcNeeded = true; o.measuringFooter = &measuringHFLoader.addResource( MultiPageLoader::guessUrlFromString(s.footer.htmlUrl), s.load)->page; } else { // or just set static values // add spacing to prevent moving footer out of page o.footerReserveHeight = settings.margin.bottom.first + s.footer.spacing; } } #endif if (!s.isTableOfContent) { o.loaderObject = pageLoader.addResource(s.page, s.load, &o.data); o.page = &o.loaderObject->page; PageObject::webPageToObject[o.page] = &o; updateWebSettings(o.page->settings(), s.web); } } emit out.phaseChanged(); loadProgress(0); #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ if (headerHeightsCalcNeeded) { // preload header/footer to check their heights measuringHFLoader.load(); } else { // set defaults if top or bottom mergin is not specified if (settings.margin.top.first == -1) { settings.margin.top.first = 10; } if (settings.margin.bottom.first == -1) { settings.margin.bottom.first = 10; } for (QList::iterator i=objects.begin(); i != objects.end(); ++i) { PageObject & o=*i; o.headerReserveHeight = settings.margin.top.first; o.footerReserveHeight = settings.margin.bottom.first; } pageLoader.load(); } #else pageLoader.load(); #endif } #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ // calculates header/footer height // returns millimeters qreal PdfConverterPrivate::calculateHeaderHeight(PageObject & object, QWebPage & header) { Q_UNUSED(object); TempFile tempObj; QString tempFile = tempObj.create(".pdf"); QPainter * testPainter = new QPainter(); QPrinter * testPrinter = createPrinter(tempFile); if (!testPainter->begin(testPrinter)) { emit out.error("Unable to write to temp location"); return 0.0; } QWebPrinter wp(header.mainFrame(), testPrinter, *testPainter); qreal height = wp.elementLocation(header.mainFrame()->findFirstElement("body")).second.height(); delete testPainter; delete testPrinter; return (height / PdfConverter::millimeterToPointMultiplier); } #endif QPrinter * PdfConverterPrivate::createPrinter(const QString & tempFile) { QPrinter * printer = new QPrinter(settings.resolution); //Tell the printer object to print the file printer->setOutputFileName(tempFile); printer->setOutputFormat(QPrinter::PdfFormat); printer->setResolution(settings.dpi); if ((settings.size.height.first != -1) && (settings.size.width.first != -1)) { printer->setPaperSize(QSizeF(settings.size.width.first,settings.size.height.first + 100), settings.size.height.second); } else { printer->setPaperSize(settings.size.pageSize); } printer->setOrientation(settings.orientation); printer->setColorMode(settings.colorMode); printer->setCreator("wkhtmltopdf " STRINGIZE(FULL_VERSION)); return printer; } #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ void PdfConverterPrivate::preprocessPage(PageObject & obj) { currentObject++; if (obj.settings.isTableOfContent) { obj.pageCount = 1; pageCount += 1; outline->addEmptyWebPage(); return; } if (!obj.loaderObject || obj.loaderObject->skip) return; int tot = objects.size(); progressString = QString("Object ")+QString::number(currentObject)+QString(" of ")+QString::number(tot); emit out.progressChanged((currentObject)*100 / tot); painter->save(); if (viewportSize.isValid() && ! viewportSize.isEmpty()) { obj.page->setViewportSize(viewportSize); obj.page->mainFrame()->setScrollBarPolicy(Qt::Vertical,Qt::ScrollBarAlwaysOff); obj.page->mainFrame()->setScrollBarPolicy(Qt::Horizontal,Qt::ScrollBarAlwaysOff); } obj.web_printer = new QWebPrinter(obj.page->mainFrame(), printer, *painter); obj.pageCount = obj.settings.pagesCount? obj.web_printer->pageCount(): 0; pageCount += obj.pageCount; if (obj.settings.includeInOutline) outline->addWebPage(obj.page->mainFrame()->title(), *obj.web_printer, obj.page->mainFrame(), obj.settings, obj.localLinks, obj.anchors); else outline->addEmptyWebPage(); painter->restore(); } #endif /*! * Prepares printing out the document to the pdf file */ void PdfConverterPrivate::pagesLoaded(bool ok) { if (errorCode == 0) errorCode = pageLoader.httpErrorCode(); if (!ok) { fail(); return; } lout = settings.out; if (settings.out == "-") { #ifndef Q_OS_WIN32 if (QFile::exists("/dev/stdout")) lout = "/dev/stdout"; else #endif lout = tempOut.create(".pdf"); } if (settings.out.isEmpty()) lout = tempOut.create(".pdf"); printer = new QPrinter(settings.resolution); //Tell the printer object to print the file printer->setOutputFileName(lout); printer->setOutputFormat(QPrinter::PdfFormat); printer->setResolution(settings.dpi); //We currently only support margins with the same unit if (settings.margin.left.second != settings.margin.right.second || settings.margin.left.second != settings.margin.top.second || settings.margin.left.second != settings.margin.bottom.second) { emit out.error("Currently all margin units must be the same!"); fail(); return; } //Setup margins and papersize #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ double maxHeaderHeight = objects[0].headerReserveHeight; double maxFooterHeight = objects[0].footerReserveHeight; for (QList::iterator i=objects.begin(); i != objects.end(); ++i) { PageObject & o=*i; maxHeaderHeight = std::max(maxHeaderHeight, o.headerReserveHeight); maxFooterHeight = std::max(maxFooterHeight, o.footerReserveHeight); } printer->setPageMargins(settings.margin.left.first, maxHeaderHeight, settings.margin.right.first, maxFooterHeight, settings.margin.left.second); #else printer->setPageMargins(settings.margin.left.first, settings.margin.top.first, settings.margin.right.first, settings.margin.bottom.first, settings.margin.left.second); #endif if ((settings.size.height.first != -1) && (settings.size.width.first != -1)) { printer->setPaperSize(QSizeF(settings.size.width.first,settings.size.height.first), settings.size.height.second); } else { printer->setPaperSize(settings.size.pageSize); } printer->setOrientation(settings.orientation); printer->setColorMode(settings.colorMode); printer->setCreator("wkhtmltopdf " STRINGIZE(FULL_VERSION)); if (!printer->isValid()) { emit out.error("Unable to write to destination"); fail(); return; } #ifndef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ //If you do not have the hacks you get this crappy solution printer->setCopyCount(settings.copies); printer->setCollateCopies(settings.collate); printDocument(); #else printer->printEngine()->setProperty(QPrintEngine::PPK_UseCompression, settings.useCompression); printer->printEngine()->setProperty(QPrintEngine::PPK_ImageQuality, settings.imageQuality); printer->printEngine()->setProperty(QPrintEngine::PPK_ImageDPI, settings.imageDPI); painter = new QPainter(); title = settings.documentTitle; for (int d=0; d < objects.size(); ++d) { if (title != "") break; if (!objects[d].loaderObject || objects[d].loaderObject->skip || objects[d].settings.isTableOfContent) continue; title = objects[d].page->mainFrame()->title(); } printer->setDocName(title); if (!painter->begin(printer)) { emit out.error("Unable to write to destination"); fail(); return; } currentPhase = 1; emit out.phaseChanged(); outline = new Outline(settings); //This is the first render face, it is done to calculate: // * The number of pages of each document // * A visual ordering of the header element // * The location and page number of each header pageCount = 0; currentObject = 0; for (int d=0; d < objects.size(); ++d) preprocessPage(objects[d]); actualPages = pageCount * settings.copies; loadTocs(); #endif } void PdfConverterPrivate::loadHeaders() { #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ currentPhase = 4; emit out.phaseChanged(); bool hf=false; int pageNumber=1; for (int d=0; d < objects.size(); ++d) { PageObject & obj = objects[d]; if (!obj.loaderObject || obj.loaderObject->skip) continue; settings::PdfObject & ps = obj.settings; for (int op=0; op < obj.pageCount; ++op) { if (!ps.header.htmlUrl.isEmpty() || !ps.footer.htmlUrl.isEmpty()) { QHash parms; fillParms(parms, pageNumber, obj); parms["sitepage"] = QString::number(op+1); parms["sitepages"] = QString::number(obj.pageCount); hf = true; if (!ps.header.htmlUrl.isEmpty()) obj.headers.push_back(loadHeaderFooter(ps.header.htmlUrl, parms, ps) ); if (!ps.footer.htmlUrl.isEmpty()) { obj.footers.push_back(loadHeaderFooter(ps.footer.htmlUrl, parms, ps) ); } } if (ps.pagesCount) ++pageNumber; } } if (hf) hfLoader.load(); else printDocument(); #endif } void PdfConverterPrivate::loadTocs() { #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ std::swap(tocLoaderOld, tocLoader); tocLoader->clearResources(); bool toc = false; for (int d=0; d < objects.size(); ++d) { PageObject & obj = objects[d]; settings::PdfObject & ps = obj.settings; if (!ps.isTableOfContent) continue; obj.clear(); QString style = ps.tocXsl; if (style.isEmpty()) { style = obj.tocFile.create(".xsl"); StreamDumper styleDump(style); dumpDefaultTOCStyleSheet(styleDump.stream, ps.toc); } QString path = obj.tocFile.create(".xml"); StreamDumper sd(path); outline->dump(sd.stream); QFile styleFile(style); if (!styleFile.open(QIODevice::ReadOnly)) { emit out.error("Could not read the TOC XSL"); fail(); } QFile xmlFile(path); if (!xmlFile.open(QIODevice::ReadOnly)) { emit out.error("Could not read the TOC XML"); fail(); } QString htmlPath = obj.tocFile.create(".html"); QFile htmlFile(htmlPath); if (!htmlFile.open(QIODevice::WriteOnly)) { emit out.error("Could not open the TOC for writing"); fail(); } QXmlQuery query(QXmlQuery::XSLT20); query.setFocus(&xmlFile); query.setQuery(&styleFile); query.evaluateTo(&htmlFile); obj.loaderObject = tocLoader->addResource(htmlPath, ps.load); obj.page = &obj.loaderObject->page; PageObject::webPageToObject[obj.page] = &obj; updateWebSettings(obj.page->settings(), ps.web); toc= true; } if (toc) { if (currentPhase != 2) { currentPhase = 2; emit out.phaseChanged(); } tocLoader->load(); } else tocLoaded(true); #endif } #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ void PdfConverterPrivate::findLinks(QWebFrame * frame, QVector > & local, QVector > & external, QHash & anchors) { bool ulocal=true, uexternal=true; if (PageObject::webPageToObject.contains(frame->page())) { ulocal = PageObject::webPageToObject[frame->page()]->settings.useLocalLinks; uexternal = PageObject::webPageToObject[frame->page()]->settings.useExternalLinks; } if (!ulocal && !uexternal) return; foreach (const QWebElement & elm, frame->findAllElements("a")) { QString n=elm.attribute("name"); if (n.isEmpty()) n=elm.attribute("ns0:name"); if (n.startsWith("__WKANCHOR_")) anchors[n] = elm; QString h=elm.attribute("href"); if (h.isEmpty()) h=elm.attribute("ns0:href"); if (h.startsWith("__WKANCHOR_")) { local.push_back( qMakePair(elm, h) ); } else { QUrl href(h); if (href.isEmpty()) continue; href=frame->baseUrl().resolved(href); QString key = QUrl::fromPercentEncoding(href.toString(QUrl::RemoveFragment).toLocal8Bit()); if (urlToPageObj.contains(key)) { if (ulocal) { PageObject * p = urlToPageObj[key]; QWebElement e; if (!href.hasFragment()) e = p->page->mainFrame()->findFirstElement("body"); else { e = p->page->mainFrame()->findFirstElement("a[name=\""+href.fragment()+"\"]"); if (e.isNull()) e = p->page->mainFrame()->findFirstElement("*[id=\""+href.fragment()+"\"]"); if (e.isNull()) e = p->page->mainFrame()->findFirstElement("*[name=\""+href.fragment()+"\"]"); } if (!e.isNull()) { p->anchors[href.toString()] = e; local.push_back( qMakePair(elm, href.toString()) ); } } } else if (uexternal) { external.push_back( qMakePair(elm, settings.resolveRelativeLinks ? href.toString() : h) ); } } } } void PdfConverterPrivate::fillParms(QHash & parms, int page, const PageObject & object) { outline->fillHeaderFooterParms(page, parms, object.settings); parms["doctitle"] = title; parms["title"] = object.page?object.page->mainFrame()->title():""; QDateTime t(QDateTime::currentDateTime()); parms["time"] = t.time().toString(Qt::SystemLocaleShortDate); parms["date"] = t.date().toString(Qt::SystemLocaleShortDate); parms["isodate"] = t.date().toString(Qt::ISODate); } void PdfConverterPrivate::endPage(PageObject & object, bool hasHeaderFooter, int objectPage, int pageNumber) { typedef QPair p_t; settings::PdfObject & s = object.settings; // save margin values qreal leftMargin, topMargin, rightMargin, bottomMargin; printer->getPageMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin, settings.margin.left.second); if (hasHeaderFooter) { QHash parms; fillParms(parms, pageNumber, object); parms["sitepage"] = QString::number(objectPage+1); parms["sitepages"] = QString::number(object.pageCount); //Webkit used all kinds of crazy coordinate transformation, and font setup //We save it here and restore some sane defaults painter->save(); painter->resetTransform(); int h=printer->height(); int w=printer->width(); double spacing = s.header.spacing * printer->height() / printer->heightMM(); //If needed draw the header line if (s.header.line) painter->drawLine(0, -spacing, w, -spacing); //Guess the height of the header text painter->setFont(QFont(s.header.fontName, s.header.fontSize)); int dy = painter->boundingRect(0, 0, w, h, Qt::AlignTop, "M").height(); //Draw the header text QRect r=QRect(0, 0-dy-spacing, w, h); painter->drawText(r, Qt::AlignTop | Qt::AlignLeft, hfreplace(s.header.left, parms)); painter->drawText(r, Qt::AlignTop | Qt::AlignHCenter, hfreplace(s.header.center, parms)); painter->drawText(r, Qt::AlignTop | Qt::AlignRight, hfreplace(s.header.right, parms)); spacing = s.footer.spacing * printer->height() / printer->heightMM(); //IF needed draw the footer line if (s.footer.line) painter->drawLine(0, h + spacing, w, h + spacing); //Guess the height of the footer text painter->setFont(QFont(s.footer.fontName, s.footer.fontSize)); dy = painter->boundingRect(0, 0, w, h, Qt::AlignTop, "M").height(); //Draw the footer text r=QRect(0,0,w,h+dy+ spacing); painter->drawText(r, Qt::AlignBottom | Qt::AlignLeft, hfreplace(s.footer.left, parms)); painter->drawText(r, Qt::AlignBottom | Qt::AlignHCenter, hfreplace(s.footer.center, parms)); painter->drawText(r, Qt::AlignBottom | Qt::AlignRight, hfreplace(s.footer.right, parms)); //Restore Webkit's crazy scaling and font settings painter->restore(); } //if (!object.headers.empty()) { //object.headers[objectPage]; if (currentHeader) { QWebPage * header = currentHeader; updateWebSettings(header->settings(), object.settings.web); painter->save(); painter->resetTransform(); QPalette pal = header->palette(); pal.setBrush(QPalette::Base, Qt::transparent); header->setPalette(pal); double spacing = s.header.spacing * printer->height() / printer->heightMM(); // clear vertical margins for proper header rendering printer->setPageMargins(leftMargin, 0, rightMargin, 0, settings.margin.left.second); painter->translate(0, -spacing); QWebPrinter wp(header->mainFrame(), printer, *painter); painter->translate(0,-wp.elementLocation(header->mainFrame()->findFirstElement("body")).second.height()); QVector local; QVector external; QHash anchors; findLinks(header->mainFrame(), local, external, anchors); foreach (const p_t & p, local) { QRectF r = wp.elementLocation(p.first).second; painter->addLink(r, p.second); } foreach (const p_t & p, external) { QRectF r = wp.elementLocation(p.first).second; painter->addHyperlink(r, QUrl(p.second)); } wp.spoolPage(1); // restore margins printer->setPageMargins(leftMargin, topMargin, rightMargin, bottomMargin, settings.margin.left.second); painter->restore(); } if (currentFooter) { QWebPage * footer=currentFooter; updateWebSettings(footer->settings(), object.settings.web); painter->save(); painter->resetTransform(); QPalette pal = footer->palette(); pal.setBrush(QPalette::Base, Qt::transparent); footer->setPalette(pal); double spacing = s.footer.spacing * printer->height() / printer->heightMM(); painter->translate(0, printer->height()+ spacing); // clear vertical margins for proper header rendering printer->setPageMargins(leftMargin, 0, rightMargin, 0, settings.margin.left.second); QWebPrinter wp(footer->mainFrame(), printer, *painter); QVector local; QVector external; QHash anchors; findLinks(footer->mainFrame(), local, external, anchors); foreach (const p_t & p, local) { QRectF r = wp.elementLocation(p.first).second; painter->addLink(r, p.second); } foreach (const p_t & p, external) { QRectF r = wp.elementLocation(p.first).second; painter->addHyperlink(r, QUrl(p.second)); } wp.spoolPage(1); // restore margins printer->setPageMargins(leftMargin, topMargin, rightMargin, bottomMargin, settings.margin.left.second); painter->restore(); } } void PdfConverterPrivate::handleTocPage(PageObject & obj) { painter->save(); QWebPrinter wp(obj.page->mainFrame(), printer, *painter); int pc = obj.settings.pagesCount? wp.pageCount(): 0; if (pc != obj.pageCount) { obj.pageCount = pc; tocChanged=true; } pageCount += obj.pageCount; tocChanged = outline->replaceWebPage(obj.number, obj.settings.toc.captionText, wp, obj.page->mainFrame(), obj.settings, obj.localLinks, obj.anchors) || tocChanged; painter->restore(); } #endif void PdfConverterPrivate::tocLoaded(bool ok) { #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ if (errorCode == 0) errorCode = tocLoader->httpErrorCode(); #endif if (!ok) { fail(); return; } #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ tocChanged = false; pageCount = 0; currentObject = 0; for (int d=0; d < objects.size(); ++d) { ++currentObject; if (!objects[d].loaderObject || objects[d].loaderObject->skip) continue; if (!objects[d].settings.isTableOfContent) { pageCount += objects[d].pageCount; continue; } handleTocPage(objects[d]); } actualPages = pageCount * settings.copies; if (tocChanged) loadTocs(); else { //Find and resolve all local links currentPhase = 3; emit out.phaseChanged(); QHash urlToDoc; for (int d=0; d < objects.size(); ++d) { if (!objects[d].loaderObject || objects[d].loaderObject->skip) continue; if (objects[d].settings.isTableOfContent) continue; urlToPageObj[ QUrl::fromPercentEncoding(objects[d].page->mainFrame()->url().toString(QUrl::RemoveFragment).toLocal8Bit()) ] = &objects[d]; } for (int d=0; d < objects.size(); ++d) { if (!objects[d].loaderObject || objects[d].loaderObject->skip) continue; progressString = QString("Object ")+QString::number(d+1)+QString(" of ")+QString::number(objects.size()); emit out.progressChanged((d+1)*100 / objects.size()); findLinks(objects[d].page->mainFrame(), objects[d].localLinks, objects[d].externalLinks, objects[d].anchors ); } loadHeaders(); } #endif } void PdfConverterPrivate::measuringHeadersLoaded(bool ok) { #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ if (errorCode == 0) errorCode = measuringHFLoader.httpErrorCode(); #endif if (!ok) { fail(); return; } #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ for (int d=0; d < objects.size(); ++d) { PageObject & obj = objects[d]; if (obj.measuringHeader) { // add spacing to prevent moving header out of page obj.headerReserveHeight = calculateHeaderHeight(obj, *obj.measuringHeader) + obj.settings.header.spacing; } if (obj.measuringFooter) { // add spacing to prevent moving footer out of page obj.footerReserveHeight = calculateHeaderHeight(obj, *obj.measuringFooter) + obj.settings.footer.spacing; } } #endif pageLoader.load(); } void PdfConverterPrivate::headersLoaded(bool ok) { #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ if (errorCode == 0) errorCode = hfLoader.httpErrorCode(); #endif if (!ok) { fail(); return; } printDocument(); } #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ void PdfConverterPrivate::spoolPage(int page) { progressString = QString("Page ") + QString::number(actualPage) + QString(" of ") + QString::number(actualPages); emit out.progressChanged(actualPage * 100 / actualPages); if (actualPage != 1) printer->newPage(); QWebPrinter *webPrinter = objects[currentObject].web_printer; webPrinter->spoolPage(page+1); foreach (QWebElement elm, pageFormElements[page+1]) { QString type = elm.attribute("type"); QString tn = elm.tagName(); QString name = elm.attribute("name"); if (tn == "TEXTAREA" || type == "text" || type == "password") { painter->addTextField( webPrinter->elementLocation(elm).second, tn == "TEXTAREA"?elm.toPlainText():elm.attribute("value"), name, tn == "TEXTAREA", type == "password", elm.evaluateJavaScript("this.readOnly;").toBool(), elm.hasAttribute("maxlength")?elm.attribute("maxlength").toInt():-1 ); } else if (type == "checkbox") { painter->addCheckBox( webPrinter->elementLocation(elm).second, elm.evaluateJavaScript("this.checked;").toBool(), name, elm.evaluateJavaScript("this.readOnly;").toBool()); } } for (QHash::iterator i=pageAnchors[page+1].begin(); i != pageAnchors[page+1].end(); ++i) { QRectF r = webPrinter->elementLocation(i.value()).second; painter->addAnchor(r, i.key()); } for (QVector< QPair >::iterator i=pageLocalLinks[page+1].begin(); i != pageLocalLinks[page+1].end(); ++i) { QRectF r = webPrinter->elementLocation(i->first).second; painter->addLink(r, i->second); } for (QVector< QPair >::iterator i=pageExternalLinks[page+1].begin(); i != pageExternalLinks[page+1].end(); ++i) { QRectF r = webPrinter->elementLocation(i->first).second; painter->addHyperlink(r, QUrl(i->second)); } endPage(objects[currentObject], pageHasHeaderFooter, page, pageNumber); actualPage++; } void PdfConverterPrivate::spoolTo(int page) { int pc=settings.collate?1:settings.copies; const settings::PdfObject & ps = objects[currentObject].settings; while (objectPage < page) { for (int pc_=0; pc_ < pc; ++pc_) spoolPage(objectPage); if (ps.pagesCount) ++pageNumber; ++objectPage; //TODO free header and footer currentHeader=NULL; currentFooter=NULL; } } void PdfConverterPrivate::beginPrintObject(PageObject & obj) { if (obj.number != 0) endPrintObject(objects[obj.number-1]); currentObject = obj.number; QWebPrinter *webPrinter = objects[currentObject].web_printer; if (!obj.loaderObject || obj.loaderObject->skip || webPrinter == 0) return; QPalette pal = obj.loaderObject->page.palette(); pal.setBrush(QPalette::Base, Qt::transparent); obj.loaderObject->page.setPalette(pal); const settings::PdfObject & ps = obj.settings; pageHasHeaderFooter = ps.header.line || ps.footer.line || !ps.header.left.isEmpty() || !ps.footer.left.isEmpty() || !ps.header.center.isEmpty() || !ps.footer.center.isEmpty() || !ps.header.right.isEmpty() || !ps.footer.right.isEmpty(); painter->save(); if (ps.produceForms) { foreach (QWebElement elm, obj.page->mainFrame()->findAllElements("input")) elm.setStyleProperty("color","white"); foreach (QWebElement elm, obj.page->mainFrame()->findAllElements("textarea")) elm.setStyleProperty("color","white"); } outline->fillAnchors(obj.number, obj.anchors); //Sort anchors and links by page for (QHash::iterator i=obj.anchors.begin(); i != obj.anchors.end(); ++i) pageAnchors[webPrinter->elementLocation(i.value()).first][i.key()] = i.value(); for (QVector< QPair >::iterator i=obj.localLinks.begin(); i != obj.localLinks.end(); ++i) pageLocalLinks[webPrinter->elementLocation(i->first).first].push_back(*i); for (QVector< QPair >::iterator i=obj.externalLinks.begin(); i != obj.externalLinks.end(); ++i) pageExternalLinks[webPrinter->elementLocation(i->first).first].push_back(*i); if (ps.produceForms) { foreach (const QWebElement & elm, obj.page->mainFrame()->findAllElements("input")) pageFormElements[webPrinter->elementLocation(elm).first].push_back(elm); foreach (const QWebElement & elm, obj.page->mainFrame()->findAllElements("textarea")) pageFormElements[webPrinter->elementLocation(elm).first].push_back(elm); } emit out.producingForms(obj.settings.produceForms); out.emitCheckboxSvgs(obj.settings.load); objectPage = 0; } void PdfConverterPrivate::handleHeader(QWebPage * frame, int page) { spoolTo(page); currentHeader = frame; } void PdfConverterPrivate::handleFooter(QWebPage * frame, int page) { spoolTo(page); currentFooter = frame; } void PdfConverterPrivate::endPrintObject(PageObject & obj) { Q_UNUSED(obj); // If this page was skipped, we might not have // anything to spool to printer.. if (obj.web_printer != 0) spoolTo(obj.web_printer->pageCount()); pageAnchors.clear(); pageLocalLinks.clear(); pageExternalLinks.clear(); pageFormElements.clear(); if (obj.web_printer != 0) { delete obj.web_printer; obj.web_printer = 0; painter->restore(); } } #endif void PdfConverterPrivate::printDocument() { #ifndef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ currentPhase = 1; emit out.phaseChanged(); objects[0].page->mainFrame()->print(printer); progressString = ""; emit out.progressChanged(-1); #else actualPage=1; int cc=settings.collate?settings.copies:1; currentPhase = 5; emit out.phaseChanged(); progressString = "Preparing"; emit out.progressChanged(0); for (int cc_=0; cc_ < cc; ++cc_) { pageNumber=1; for (int d=0; d < objects.size(); ++d) { beginPrintObject(objects[d]); // XXX: In some cases nothing gets loaded at all, // so we would get no webPrinter instance. int pageCount = objects[d].web_printer != 0 ? objects[d].web_printer->pageCount() : 0; //const settings::PdfObject & ps = objects[d].settings; for(int i=0; i < pageCount; ++i) { if (!objects[d].headers.empty()) handleHeader(objects[d].headers[i], i); if (!objects[d].footers.empty()) handleFooter(objects[d].footers[i], i); } } endPrintObject(objects[objects.size()-1]); } outline->printOutline(printer); if (!settings.dumpOutline.isEmpty()) { StreamDumper sd(settings.dumpOutline); outline->dump(sd.stream); } painter->end(); #endif if (settings.out == "-" && lout != "/dev/stdout") { QFile i(lout); QFile o; #ifdef Q_OS_WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif if ( !i.open(QIODevice::ReadOnly) || !o.open(stdout,QIODevice::WriteOnly) || !MultiPageLoader::copyFile(i,o) ) { emit out.error("Count not write to stdout"); tempOut.removeAll(); fail(); return; } tempOut.removeAll(); } if (settings.out.isEmpty()) { QFile i(lout); if (!i.open(QIODevice::ReadOnly)) { emit out.error("Reading output failed"); tempOut.removeAll(); fail(); } outputData = i.readAll(); i.close(); tempOut.removeAll(); } clearResources(); #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ currentPhase = 6; #else currentPhase = 2; #endif emit out.phaseChanged(); conversionDone = true; emit out.finished(true); qApp->exit(0); // quit qt's event handling } #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ QWebPage * PdfConverterPrivate::loadHeaderFooter(QString url, const QHash & parms, const settings::PdfObject & ps) { QUrl u = MultiPageLoader::guessUrlFromString(url); for (QHash::const_iterator i=parms.begin(); i != parms.end(); ++i) u.addQueryItem(i.key(), i.value()); return &hfLoader.addResource(u, ps.load)->page; } /*! * Replace some variables in a string used in a header or footer * \param q the string to substitute in */ QString PdfConverterPrivate::hfreplace(const QString & q, const QHash & parms) { QString r=q; for (QHash::const_iterator i=parms.begin(); i != parms.end(); ++i) r=r.replace("["+i.key()+"]", i.value(), Qt::CaseInsensitive); return r; } #endif void PdfConverterPrivate::clearResources() { objects.clear(); pageLoader.clearResources(); #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ hfLoader.clearResources(); tocLoader1.clearResources(); tocLoader2.clearResources(); if (outline) { Outline * tmp = outline; outline = 0; delete tmp; } #endif if (printer) { QPrinter * tmp = printer; printer = 0; delete tmp; } if (painter) { QPainter * tmp = painter; painter = 0; delete tmp; } } Converter & PdfConverterPrivate::outer() { return out; } /*! \class PdfConverter \brief Class responsible for converting html pages to pdf \todo explain something about the conversion process here, and mention stages */ /*! \brief Create a page converter object based on the supplied settings \param settings Settings for the conversion */ PdfConverter::PdfConverter(settings::PdfGlobal & settings): d(new PdfConverterPrivate(settings, *this)) { } /*! \brief The destructor for the page converter object */ PdfConverter::~PdfConverter() { PdfConverterPrivate *tmp = d; d = 0; tmp->deleteLater();; } /*! \brief add a resource we want to convert \param url The url of the object we want to convert */ void PdfConverter::addResource(const settings::PdfObject & page, const QString * data) { d->objects.push_back( PageObject(page, data) ); d->objects.back().number = d->objects.size()-1; } const QByteArray & PdfConverter::output() { return d->outputData; } /*! \brief Returns the settings object associated with the page converter */ const settings::PdfGlobal & PdfConverter::globalSettings() const { return d->settings; } /*! \fn PdfConverter::warning(const QString & message) \brief Signal emitted when some non fatal warning occurs during conversion \param message The warning message */ /*! \fn PdfConverter::error(const QString & message) \brief Signal emitted when a fatal error has occurred during conversion \param message A message describing the fatal error */ /*! \fn PdfConverter::phaseChanged() \brief Signal emitted when the converter has reached a new phase */ /*! \fn PdfConverter::progressChanged() \brief Signal emitted when some progress has been done in the conversion phase */ /*! \fn PdfConverter::finised() \brief Signal emitted when conversion has finished. */ ConverterPrivate & PdfConverter::priv() { return *d; } wkhtmltopdf-0.12.5/src/lib/pdfconverter.hh000066400000000000000000000032141343154624600205310ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __PDFCONVERTER_HH__ #define __PDFCONVERTER_HH__ #include #include #include namespace wkhtmltopdf { class DLL_LOCAL PdfConverterPrivate; class DLL_PUBLIC PdfConverter: public Converter { Q_OBJECT public: PdfConverter(settings::PdfGlobal & globalSettings); ~PdfConverter(); int pageCount(); void addResource(const settings::PdfObject & pageSettings, const QString * data=0); const settings::PdfGlobal & globalSettings() const; const QByteArray & output(); static const qreal millimeterToPointMultiplier; private: PdfConverterPrivate * d; virtual ConverterPrivate & priv(); friend class PdfConverterPrivate; signals: void producingForms(bool); }; } #include #endif //__PDFCONVERTER_HH__ wkhtmltopdf-0.12.5/src/lib/pdfconverter_p.hh000066400000000000000000000130251343154624600210510ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __PDFCONVERTER_P_HH__ #define __PDFCONVERTER_P_HH__ #include "converter_p.hh" #include "multipageloader.hh" #include "outline.hh" #include "pdfconverter.hh" #include "pdfsettings.hh" #include "tempfile.hh" #include #include #include #include #include #include #include #include #include #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ #include #endif #include "dllbegin.inc" namespace wkhtmltopdf { class DLL_LOCAL PageObject { public: static QMap webPageToObject; settings::PdfObject settings; LoaderObject * loaderObject; QWebPage * page; QString data; int number; #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ QHash anchors; QVector< QPair > localLinks; QVector< QPair > externalLinks; // height length to reserve for header when printing page double headerReserveHeight; // height length to reserve for footer when printing page double footerReserveHeight; // keeps preloaded header to calculate header height QWebPage * measuringHeader; // keeps preloaded footer to calculate header height QWebPage * measuringFooter; // webprinter instance QWebPrinter *web_printer; #endif int firstPageNumber; QList headers; QList footers; int pageCount; TempFile tocFile; void clear() { #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ anchors.clear(); localLinks.clear(); externalLinks.clear(); if (web_printer != 0) delete web_printer; web_printer=0; #endif headers.clear(); footers.clear(); webPageToObject.remove(page); page=0; tocFile.removeAll(); } PageObject(const settings::PdfObject & set, const QString * d=NULL): settings(set), loaderObject(0), page(0) #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ , headerReserveHeight(0), footerReserveHeight(0), measuringHeader(0), measuringFooter(0), web_printer(0) #endif { if (d) data=*d; }; ~PageObject() { clear(); } }; class DLL_LOCAL PdfConverterPrivate: public ConverterPrivate { Q_OBJECT public: PdfConverterPrivate(settings::PdfGlobal & s, PdfConverter & o); ~PdfConverterPrivate(); settings::PdfGlobal & settings; MultiPageLoader pageLoader; private: PdfConverter & out; void clearResources(); TempFile tempOut; QByteArray outputData; QList objects; QSize viewportSize; QPrinter * printer; QPainter * painter; QString lout; QString title; int currentObject; int actualPages; int pageCount; int tocPages; bool tocChanged; int actualPage; int pageNumber; #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ int objectPage; QHash > pageAnchors; QHash > > pageLocalLinks; QHash > > pageExternalLinks; QHash > pageFormElements; bool pageHasHeaderFooter; // loader for measuringHeader and measuringFooter MultiPageLoader measuringHFLoader; MultiPageLoader hfLoader; MultiPageLoader tocLoader1; MultiPageLoader tocLoader2; MultiPageLoader * tocLoader; MultiPageLoader * tocLoaderOld; QHash urlToPageObj; Outline * outline; void findLinks(QWebFrame * frame, QVector > & local, QVector > & external, QHash & anchors); void endPage(PageObject & object, bool hasHeaderFooter, int objectPage, int pageNumber); void fillParms(QHash & parms, int page, const PageObject & object); QString hfreplace(const QString & q, const QHash & parms); QWebPage * loadHeaderFooter(QString url, const QHash & parms, const settings::PdfObject & ps); qreal calculateHeaderHeight(PageObject & object, QWebPage & header); #endif QWebPage * currentHeader; QWebPage * currentFooter; QPrinter * createPrinter(const QString & tempFile); #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ void handleTocPage(PageObject & obj); void preprocessPage(PageObject & obj); void spoolPage(int page); void spoolTo(int page); void handleHeader(QWebPage * frame, int page); void handleFooter(QWebPage * frame, int page); void beginPrintObject(PageObject & obj); void endPrintObject(PageObject & obj); #endif void loadTocs(); void loadHeaders(); public slots: void measuringHeadersLoaded(bool ok); void pagesLoaded(bool ok); void tocLoaded(bool ok); void headersLoaded(bool ok); void printDocument(); void beginConvert(); friend class PdfConverter; virtual Converter & outer(); }; } #include "dllend.inc" #endif //__PDFCONVERTER_P_HH__ wkhtmltopdf-0.12.5/src/lib/pdfsettings.cc000066400000000000000000000304431343154624600203540ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifdef _MSC_VER #define strcasecmp _stricmp #endif #include "pdfsettings.hh" #include "reflect.hh" #include #include #include "dllbegin.inc" namespace wkhtmltopdf { namespace settings { template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { UnitReal & ur; ReflectImpl(UnitReal & _): ur(_) {} QString get() {bool d; return unitRealToStr(ur, &d);} void set(const QString & value, bool * ok) {ur = strToUnitReal(value.toUtf8().constData(), ok);} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { QPrinter::PageSize & ps; ReflectImpl(QPrinter::PageSize & _): ps(_) {} QString get() {return pageSizeToStr(ps);} void set(const QString & value, bool * ok) {ps = strToPageSize(value.toUtf8().constData(), ok);} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { QPrinter::Orientation & o; ReflectImpl(QPrinter::Orientation & _): o(_) {} QString get() {return orientationToStr(o);} void set(const QString & value, bool * ok) {o = strToOrientation(value.toUtf8().constData(), ok);} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { QPrinter::PrinterMode & m; ReflectImpl(QPrinter::PrinterMode & _): m(_) {} QString get() {return printerModeToStr(m);} void set(const QString & value, bool * ok) {m = strToPrinterMode(value.toUtf8().constData(), ok);} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { QPrinter::ColorMode & m; ReflectImpl(QPrinter::ColorMode & _): m(_) {} QString get() {return colorModeToStr(m);} void set(const QString & value, bool * ok) {m = strToColorMode(value.toUtf8().constData(), ok);} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(Margin & c) { WKHTMLTOPDF_REFLECT(top); WKHTMLTOPDF_REFLECT(right); WKHTMLTOPDF_REFLECT(bottom); WKHTMLTOPDF_REFLECT(left); } }; template<> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(Size & c) { WKHTMLTOPDF_REFLECT(pageSize); WKHTMLTOPDF_REFLECT(height); WKHTMLTOPDF_REFLECT(width); } }; template<> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(TableOfContent & c) { WKHTMLTOPDF_REFLECT(useDottedLines); WKHTMLTOPDF_REFLECT(captionText); WKHTMLTOPDF_REFLECT(forwardLinks); WKHTMLTOPDF_REFLECT(backLinks); WKHTMLTOPDF_REFLECT(indentation); WKHTMLTOPDF_REFLECT(fontScale); } }; template<> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(PdfGlobal & c) { WKHTMLTOPDF_REFLECT(size); ReflectClass::add("quiet", new QuietArgBackwardsCompatReflect(c.logLevel)); // Fake the "quiet" argument WKHTMLTOPDF_REFLECT(logLevel); WKHTMLTOPDF_REFLECT(useGraphics); WKHTMLTOPDF_REFLECT(resolveRelativeLinks); WKHTMLTOPDF_REFLECT(orientation); WKHTMLTOPDF_REFLECT(colorMode); WKHTMLTOPDF_REFLECT(resolution); WKHTMLTOPDF_REFLECT(dpi); WKHTMLTOPDF_REFLECT(pageOffset); WKHTMLTOPDF_REFLECT(copies); WKHTMLTOPDF_REFLECT(collate); WKHTMLTOPDF_REFLECT(outline); WKHTMLTOPDF_REFLECT(outlineDepth); WKHTMLTOPDF_REFLECT(dumpOutline); WKHTMLTOPDF_REFLECT(out); WKHTMLTOPDF_REFLECT(documentTitle); WKHTMLTOPDF_REFLECT(useCompression); WKHTMLTOPDF_REFLECT(margin); WKHTMLTOPDF_REFLECT(imageDPI); WKHTMLTOPDF_REFLECT(imageQuality); WKHTMLTOPDF_REFLECT(load); WKHTMLTOPDF_REFLECT(viewportSize); } }; template<> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(HeaderFooter & c) { WKHTMLTOPDF_REFLECT(fontSize); WKHTMLTOPDF_REFLECT(fontName); WKHTMLTOPDF_REFLECT(left); WKHTMLTOPDF_REFLECT(right); WKHTMLTOPDF_REFLECT(center); WKHTMLTOPDF_REFLECT(line); WKHTMLTOPDF_REFLECT(htmlUrl); WKHTMLTOPDF_REFLECT(spacing); } }; template<> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(PdfObject & c) { WKHTMLTOPDF_REFLECT(toc); WKHTMLTOPDF_REFLECT(page); WKHTMLTOPDF_REFLECT(header); WKHTMLTOPDF_REFLECT(footer); WKHTMLTOPDF_REFLECT(useExternalLinks); WKHTMLTOPDF_REFLECT(useLocalLinks); WKHTMLTOPDF_REFLECT(replacements); WKHTMLTOPDF_REFLECT(produceForms); WKHTMLTOPDF_REFLECT(load); WKHTMLTOPDF_REFLECT(web); WKHTMLTOPDF_REFLECT(includeInOutline); WKHTMLTOPDF_REFLECT(pagesCount); WKHTMLTOPDF_REFLECT(isTableOfContent); WKHTMLTOPDF_REFLECT(tocXsl); } }; /*! \file settings.hh \brief Defines the Settings class */ DLL_LOCAL QMap pageSizeMap() { QMap res; res["A0"] = QPrinter::A0; res["A1"] = QPrinter::A1; res["A2"] = QPrinter::A2; res["A3"] = QPrinter::A3; res["A4"] = QPrinter::A4; res["A5"] = QPrinter::A5; res["A6"] = QPrinter::A6; res["A7"] = QPrinter::A7; res["A8"] = QPrinter::A8; res["A9"] = QPrinter::A9; res["B0"] = QPrinter::B0; res["B1"] = QPrinter::B1; res["B10"] = QPrinter::B10; res["B2"] = QPrinter::B2; res["B3"] = QPrinter::B3; res["B4"] = QPrinter::B4; res["B5"] = QPrinter::B5; res["B6"] = QPrinter::B6; res["B7"] = QPrinter::B7; res["B8"] = QPrinter::B8; res["B9"] = QPrinter::B9; res["C5E"] = QPrinter::C5E; res["Comm10E"] = QPrinter::Comm10E; res["DLE"] = QPrinter::DLE; res["Executive"] = QPrinter::Executive; res["Folio"] = QPrinter::Folio; res["Ledger"] = QPrinter::Ledger; res["Legal"] = QPrinter::Legal; res["Letter"] = QPrinter::Letter; res["Tabloid"] = QPrinter::Tabloid; return res; } /*! Convert a string to a paper size, basically all thinkable values are allowed. if a unknown value is given A4 is returned \param s The string to convert \param ok If supplied indicates if the conversion was successful */ QPrinter::PageSize strToPageSize(const char * s, bool * ok) { QMap map = pageSizeMap(); for (QMap::const_iterator i=map.begin(); i != map.end(); ++i) { if (i.key().compare(s, Qt::CaseInsensitive) != 0) continue; if (ok) *ok=true; return i.value(); } if (ok) *ok = false; return QPrinter::A4; } QString pageSizeToStr(QPrinter::PageSize ps) { QMap map = pageSizeMap(); for (QMap::const_iterator i=map.begin(); i != map.end(); ++i) { if (i.value() == ps) return i.key(); } return ""; } /*! Read orientation from a string, possible values are landscape and portrait (case insensitive) \param s The string containing the orientation \param ok If supplied indicates whether the s was valid */ QPrinter::Orientation strToOrientation(const char * s, bool * ok) { if (ok) *ok = true; if (!strcasecmp(s,"Landscape")) return QPrinter::Landscape; if (!strcasecmp(s,"Portrait")) return QPrinter::Portrait; if (ok) *ok = false; return QPrinter::Portrait; } QString orientationToStr(QPrinter::Orientation o) { return (o == QPrinter::Landscape)?"Landscape":"Portrait"; } /*! Parse a string describing a distance, into a real number and a unit. \param o Tho string describing the distance \param ok If supplied indicates whether the s was valid */ UnitReal strToUnitReal(const char * o, bool * ok) { qreal s=1.0; //Since not all units are provided by qt, we use this variable to scale //Them into units that are. QPrinter::Unit u=QPrinter::Millimeter; //Skip the real number part int i=0; while ('0' <= o[i] && o[i] <= '9') ++i; if (o[i] == '.' || o[i] == '.') ++i; while ('0' <= o[i] && o[i] <= '9') ++i; //Try to match the unit used if (!strcasecmp(o+i,"") || !strcasecmp(o+i,"mm") || !strcasecmp(o+i,"millimeter")) { u=QPrinter::Millimeter; } else if (!strcasecmp(o+i,"cm") || !strcasecmp(o+i,"centimeter")) { u=QPrinter::Millimeter; s=10.0; //1cm=10mm } else if (!strcasecmp(o+i,"m") || !strcasecmp(o+i,"meter")) { u=QPrinter::Millimeter; s=1000.0; //1m=1000m } else if (!strcasecmp(o+i,"didot")) u=QPrinter::Didot; //Todo is there a short for didot?? else if (!strcasecmp(o+i,"inch") || !strcasecmp(o+i,"in")) u=QPrinter::Inch; else if (!strcasecmp(o+i,"pica") || !strcasecmp(o+i,"pc")) u=QPrinter::Pica; else if (!strcasecmp(o+i,"cicero")) u=QPrinter::Cicero; else if (!strcasecmp(o+i,"pixel") || !strcasecmp(o+i,"px")) u=QPrinter::DevicePixel; else if (!strcasecmp(o+i,"point") || !strcasecmp(o+i,"pt")) u=QPrinter::Point; else { if (ok) *ok=false; return UnitReal(QString(o).left(i).toDouble()*s, u); } return UnitReal(QString(o).left(i).toDouble(ok)*s, u); } QString unitRealToStr(const UnitReal & ur, bool * ok) { QString c; if (ur.first == -1) { if (ok) *ok=false; return ""; } if (ok) *ok=true; switch (ur.second) { case QPrinter::Didot: c = "didot"; break; case QPrinter::Inch: c = "in"; break; case QPrinter::Pica: c = "pica"; break; case QPrinter::DevicePixel: c = "px"; break; case QPrinter::Point: c = "pt"; break; case QPrinter::Millimeter: c = "mm"; break; default: if (ok) *ok=false; return ""; } return QString("%1%2").arg(ur.first).arg(c); } QPrinter::PrinterMode strToPrinterMode(const char * s, bool * ok) { if (ok) *ok=true; if (!strcasecmp(s,"screen")) return QPrinter::ScreenResolution; if (!strcasecmp(s,"printer")) return QPrinter::PrinterResolution; if (!strcasecmp(s,"high")) return QPrinter::HighResolution; *ok=false; return QPrinter::HighResolution; } QString printerModeToStr(QPrinter::PrinterMode o) { switch (o) { case QPrinter::ScreenResolution: return "screen"; case QPrinter::PrinterResolution: return "printer"; case QPrinter::HighResolution: return "high"; } return QString(); } QPrinter::ColorMode strToColorMode(const char * s, bool * ok) { if (ok) *ok=true; if (!strcasecmp(s,"color")) return QPrinter::Color; if (!strcasecmp(s,"grayscale")) return QPrinter::GrayScale; *ok=false; return QPrinter::Color; } QString colorModeToStr(QPrinter::ColorMode o) { switch (o) { case QPrinter::Color: return "color"; case QPrinter::GrayScale: return "grayscale"; } return QString(); } Size::Size(): pageSize(QPrinter::A4), height(UnitReal(-1,QPrinter::Millimeter)), width(UnitReal(-1,QPrinter::Millimeter)) {} HeaderFooter::HeaderFooter(): fontSize(12), fontName("Arial"), left(""), right(""), center(""), line(false), htmlUrl(""), spacing(0.0) {} Margin::Margin(): top(UnitReal(-1,QPrinter::Millimeter)), right(UnitReal(10,QPrinter::Millimeter)), bottom(UnitReal(-1,QPrinter::Millimeter)), left(UnitReal(10,QPrinter::Millimeter)) {} PdfGlobal::PdfGlobal(): logLevel(Info), useGraphics(false), resolveRelativeLinks(true), orientation(QPrinter::Portrait), colorMode(QPrinter::Color), resolution(QPrinter::HighResolution), dpi(96), pageOffset(0), copies(1), collate(true), outline(true), outlineDepth(4), dumpOutline(""), out(""), documentTitle(""), useCompression(true), viewportSize(""), imageDPI(600), imageQuality(94){}; TableOfContent::TableOfContent(): useDottedLines(true), captionText("Table of Contents"), forwardLinks(true), backLinks(false), indentation("1em"), fontScale(0.8f) {} PdfObject::PdfObject(): useExternalLinks(true), useLocalLinks(true), produceForms(false), includeInOutline(true), pagesCount(true), isTableOfContent(false), tocXsl("") {}; QString PdfGlobal::get(const char * name) { ReflectImpl impl(*this); return impl.get(name); } bool PdfGlobal::set(const char * name, const QString & value) { ReflectImpl impl(*this); return impl.set(name, value); } QString PdfObject::get(const char * name) { ReflectImpl impl(*this); return impl.get(name); } bool PdfObject::set(const char * name, const QString & value) { ReflectImpl impl(*this); return impl.set(name, value); } } } wkhtmltopdf-0.12.5/src/lib/pdfsettings.hh000066400000000000000000000133211343154624600203620ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __PDFSETTINGS_HH__ #define __PDFSETTINGS_HH__ #include #include #include #include #include #include #include namespace wkhtmltopdf { namespace settings { typedef QPair UnitReal; /*! \brief Settings considering margins */ struct DLL_PUBLIC Margin { Margin(); //!Margin applied to the top of the page UnitReal top; //!Margin applied to the right of the page UnitReal right; //!Margin applied to the bottom of the page UnitReal bottom; //!Margin applied to the leftp of the page UnitReal left; }; /*! \brief Settings considering page size */ struct DLL_PUBLIC Size { Size(); //! What size paper should we use QPrinter::PageSize pageSize; //!Height of the page UnitReal height; //!Width of the page UnitReal width; }; /*! \brief Settings considering the table of content */ struct DLL_PUBLIC TableOfContent { TableOfContent(); //! Should we print dots between the name and the page number? bool useDottedLines; //! Name af the TOC QString captionText; //! Link from TOC to section headers bool forwardLinks; //! Link from section headers to TOC bool backLinks; //! How fare should we indent on every level QString indentation; //! Factor we should scale the font with on every level float fontScale; }; /*! \brief Class holding all user setting. This class holds all the user settings, settings can be filled in by hand, or with other methods. \sa CommandLineParser::parse() */ struct DLL_PUBLIC PdfGlobal { PdfGlobal(); //! Size related settings Size size; //! Log level LogLevel logLevel; //! Should we use the graphics system bool useGraphics; //! Should relative links be resolved or kept as-is bool resolveRelativeLinks; //! Should we orientate in landscape or portrate QPrinter::Orientation orientation; //! Color or grayscale QPrinter::ColorMode colorMode; //! What overall resolution should we use QPrinter::PrinterMode resolution; //! What dpi should be used when printing int dpi; //! When pagenumbers are printed, apply this offset to them all int pageOffset; //! How many copies do we wan to print int copies; //! Should be print a whole copy before beginning the next bool collate; //! Should we generate an outline and put it into the pdf file bool outline; //! Maximal depth of the generated outline int outlineDepth; //! dump outline to this filename QString dumpOutline; //! The file where in to store the output QString out; QString documentTitle; bool useCompression; //! Margin related settings Margin margin; QString viewportSize; int imageDPI; int imageQuality; LoadGlobal load; QString get(const char * name); bool set(const char * name, const QString & value); }; /*! \brief Settings considering headers and footers */ struct DLL_PUBLIC HeaderFooter { HeaderFooter(); //! Size of the font used to render the text int fontSize; //! Name of font used to render text QString fontName; //! Text to render at the left QString left; //! Text to render at the right QString right; //! Text to render at the center QString center; //! Should a line separate the header/footer and the document bool line; //! Url of the document the html document that should be used as a header/footer QString htmlUrl; //! Spacing float spacing; }; struct DLL_PUBLIC PdfObject { PdfObject(); //! Settings regarding the TOC TableOfContent toc; QString page; //! Header related settings HeaderFooter header; //! Header related settings HeaderFooter footer; //! Should external links be links in the PDF bool useExternalLinks; //! Should internal links be links in the PDF bool useLocalLinks; //! Replacements QList< QPair > replacements; //! Convert forms on the pages into PDF forms bool produceForms; LoadPage load; Web web; bool includeInOutline; bool pagesCount; bool isTableOfContent; QString tocXsl; QString get(const char * name); bool set(const char * name, const QString & value); }; DLL_PUBLIC QPrinter::PageSize strToPageSize(const char * s, bool * ok=0); DLL_PUBLIC QString pageSizeToStr(QPrinter::PageSize ps); DLL_PUBLIC UnitReal strToUnitReal(const char * s, bool * ok=0); DLL_PUBLIC QString unitRealToStr(const UnitReal & ur, bool * ok); DLL_PUBLIC QPrinter::Orientation strToOrientation(const char * s, bool * ok=0); DLL_PUBLIC QString orientationToStr(QPrinter::Orientation o); DLL_PUBLIC QPrinter::PrinterMode strToPrinterMode(const char * s, bool * ok=0); DLL_PUBLIC QString printerModeToStr(QPrinter::PrinterMode o); DLL_PUBLIC QPrinter::ColorMode strToColorMode(const char * s, bool * ok=0); DLL_PUBLIC QString colorModeToStr(QPrinter::ColorMode o); } DLL_PUBLIC void dumpDefaultTOCStyleSheet(QTextStream & stream, settings::TableOfContent & s); } #include #endif //__PDFSETTINGS_HH__ wkhtmltopdf-0.12.5/src/lib/reflect.cc000066400000000000000000000064021343154624600174440ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "reflect.hh" namespace wkhtmltopdf { namespace settings { bool ReflectSimple::set(const char * name, const QString & value) { bool ok=false; if (name[0]=='\0') set(value, &ok); return ok; } QString ReflectClass::get(const char * name) { int i=0; while (name[i] !=0 && name[i] != '.' && name[i] != '[') ++i; if (!elms.contains(QString::fromLocal8Bit(name, i))) return QString(); return elms[QString::fromLocal8Bit(name,i)]->get(name + (name[i] == '.'?i+1:i)); } bool ReflectClass::set(const char * name, const QString & value) { int i=0; while (name[i] !=0 && name[i] != '.' && name[i] != '[') ++i; if (!elms.contains(QString::fromLocal8Bit(name, i))) return false; return elms[QString::fromLocal8Bit(name,i)]->set(name + (name[i] == '.'?i+1:i), value); } ReflectClass::~ReflectClass() { for (QMap::iterator i=elms.begin(); i != elms.end(); ++i) delete i.value(); } ReflectImpl::ReflectImpl(LoadGlobal & c) { WKHTMLTOPDF_REFLECT(cookieJar); } ReflectImpl::ReflectImpl(LoadPage & c) { WKHTMLTOPDF_REFLECT(username); WKHTMLTOPDF_REFLECT(password); WKHTMLTOPDF_REFLECT(clientSslKeyPath); WKHTMLTOPDF_REFLECT(clientSslKeyPassword); WKHTMLTOPDF_REFLECT(clientSslCrtPath); WKHTMLTOPDF_REFLECT(jsdelay); WKHTMLTOPDF_REFLECT(windowStatus); WKHTMLTOPDF_REFLECT(zoomFactor); WKHTMLTOPDF_REFLECT(customHeaders); WKHTMLTOPDF_REFLECT(repeatCustomHeaders); WKHTMLTOPDF_REFLECT(cookies); WKHTMLTOPDF_REFLECT(post); WKHTMLTOPDF_REFLECT(blockLocalFileAccess); WKHTMLTOPDF_REFLECT(allowed); WKHTMLTOPDF_REFLECT(stopSlowScripts); WKHTMLTOPDF_REFLECT(debugJavascript); WKHTMLTOPDF_REFLECT(loadErrorHandling); WKHTMLTOPDF_REFLECT(proxy); WKHTMLTOPDF_REFLECT(runScript); WKHTMLTOPDF_REFLECT(checkboxSvg); WKHTMLTOPDF_REFLECT(checkboxCheckedSvg); WKHTMLTOPDF_REFLECT(radiobuttonSvg); WKHTMLTOPDF_REFLECT(radiobuttonCheckedSvg); WKHTMLTOPDF_REFLECT(cacheDir); WKHTMLTOPDF_REFLECT(bypassProxyForHosts); WKHTMLTOPDF_REFLECT(proxyHostNameLookup); } ReflectImpl::ReflectImpl(Web & c) { WKHTMLTOPDF_REFLECT(background); WKHTMLTOPDF_REFLECT(loadImages); WKHTMLTOPDF_REFLECT(enableJavascript); WKHTMLTOPDF_REFLECT(enableIntelligentShrinking); WKHTMLTOPDF_REFLECT(minimumFontSize); WKHTMLTOPDF_REFLECT(printMediaType); WKHTMLTOPDF_REFLECT(defaultEncoding); WKHTMLTOPDF_REFLECT(userStyleSheet); WKHTMLTOPDF_REFLECT(enablePlugins); } } } wkhtmltopdf-0.12.5/src/lib/reflect.hh000066400000000000000000000161721343154624600174630ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __REFLECT_HH__ #define __REFLECT_HH__ #if defined(_MSC_VER) && _MSC_VER>=1600 #define typeof decltype #endif #include "logging.hh" #include "loadsettings.hh" #include "websettings.hh" #include #include #include "dllbegin.inc" namespace wkhtmltopdf { namespace settings { #define WKHTMLTOPDF_REFLECT(name) ReflectClass::add(#name, new ReflectImpl (c.name)); class DLL_LOCAL Reflect { public: virtual QString get(const char * name) = 0; virtual bool set(const char * name, const QString & value) = 0; virtual ~Reflect() {}; }; class DLL_LOCAL ReflectSimple: public Reflect { public: virtual QString get() = 0; virtual void set(const QString & value, bool * ok) = 0; virtual QString get(const char * name) {return name[0]=='\0'?get():QString();} virtual bool set(const char * name, const QString & value); }; class DLL_LOCAL ReflectClass: public Reflect { public: QMap elms; void add(const char * name, Reflect * r) {elms[name] = r;} QString get(const char * name); bool set(const char * name, const QString & value); ~ReflectClass(); }; class DLL_LOCAL QuietArgBackwardsCompatReflect: public ReflectSimple { LogLevel & l; public: QuietArgBackwardsCompatReflect(LogLevel & _): l(_) {} QString get() {return l == None ? "true":"false";} void set(const QString & value, bool * ok) { if (value == "true") l=None; else if (value == "false") l=Info; else { *ok=false; return; } *ok=true; } }; template class DLL_LOCAL ReflectImpl { private: ReflectImpl(); }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { LogLevel & l; ReflectImpl(LogLevel & _): l(_) { } QString get() { return logLevelToStr(l, 0); } void set(const QString & value, bool * ok) { l = strToLogLevel(qPrintable(value), ok); } }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { bool & b; ReflectImpl(bool & _): b(_) {} QString get() {return b?"true":"false";} void set(const QString & value, bool * ok) { if (value == "true") b=true; else if (value == "false") b=false; else { *ok=false; return; } *ok=true; } }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { QString & s; ReflectImpl(QString & _): s(_) {} QString get() {return s;} void set(const QString & value, bool * ok) {s=value; *ok=true;} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { int & i; ReflectImpl(int & _): i(_) {} QString get() {return QString::number(i);} void set(const QString & value, bool * ok) {i = value.toInt(ok);} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { float & f; ReflectImpl(float & _): f(_) {} QString get() {return QString::number(f);} void set(const QString & value, bool * ok) {f = value.toDouble(ok);} }; template<> struct DLL_LOCAL ReflectImpl< QPair >: public ReflectSimple { QPair & p; ReflectImpl(QPair & _): p(_) {}; QString get() { return p.first + "\n" + p.second; } void set(const QString & value, bool * ok) { QStringList l = value.split("\n"); if (l.size() != 2) {*ok=false; return;} *ok = true; p.first = l[0]; p.second = l[1]; } }; template struct DLL_LOCAL ReflectImpl< QList< X> >: public Reflect { QList & l; ReflectImpl(QList & _): l(_) {} bool parse(const char * name, int & parmsize, int & next, int & elm) { elm=-1; parmsize = -1; if (name[0] == '[') { next = 0; while (name[next] != '\0' && name[next] != ']') ++next; bool ok=true; elm = QString::fromLocal8Bit(name+1,next-1).toInt(&ok); while (name[next] == ']' || name[next] == '.') ++next; return ok; } parmsize = 0; while (name[parmsize] != '\0' && name[parmsize] != '.' && name[parmsize] != '[') ++parmsize; next = parmsize; if (name[next] == '.') ++next; return true; } virtual QString get(const char * name) { int ps, next, elm; if (!strcmp(name,"size") || !strcmp(name,"length") || !strcmp(name,"count")) return QString::number(l.size()); if (!parse(name, ps, next, elm)) return QString(); if (ps > 0 && !l.isEmpty() && !strncmp(name, "first", ps)) elm = 0; if (ps > 0 && !l.isEmpty() && !strncmp(name, "last", ps)) elm = l.size() - 1; if (elm < 0 || elm >= l.size()) return QString(); ReflectImpl impl(l[elm]); return static_cast(&impl)->get(name+next); }; virtual bool set(const char * name, const QString & value) { int ps, next, elm; if (!strcmp(name,"clear")) l.clear(); else if (!strcmp(name,"append")) l.append(X()); else if (!strcmp(name,"prepend")) l.prepend(X()); else if (!strcmp(name,"delete")) { bool ok = true; int idx = value.toInt(&ok); if (ok && idx >= 0 && idx < l.size()) { l.removeAt(idx); return true; } return false; } else { if (!parse(name, ps, next, elm)) return false; if (ps > 0 && !l.isEmpty() && !strncmp(name, "first", ps)) elm = 0; if (ps > 0 && !l.isEmpty() && !strncmp(name, "last", ps)) elm = l.size() - 1; ReflectImpl impl(l[elm]); return static_cast(&impl)->set(name+next, value); } return true; } }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { LoadPage::LoadErrorHandling & l; ReflectImpl(LoadPage::LoadErrorHandling & _): l(_) {} QString get() {return loadErrorHandlingToStr(l);} void set(const QString & value, bool * ok) {l = strToLoadErrorHandling(value.toUtf8().constData(), ok);} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { Proxy & p; ReflectImpl(Proxy & _): p(_) {} QString get() {return proxyToStr(p);} void set(const QString & value, bool * ok) {p = strToProxy(value.toUtf8().constData(), ok);} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(PostItem & c) { WKHTMLTOPDF_REFLECT(name); WKHTMLTOPDF_REFLECT(value); WKHTMLTOPDF_REFLECT(file); } }; template <> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(LoadGlobal & c); }; template <> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(LoadPage & c); }; template <> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(Web & c); }; } } #include "dllend.inc" #endif //__REFLECT_HH__ wkhtmltopdf-0.12.5/src/lib/tempfile.cc000066400000000000000000000032631343154624600176270ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "tempfile.hh" #include #include #include #include "dllbegin.inc" /*! \file tempfile.hh \brief Defines the TempFile class */ /*! \class TempFile \brief Class responsible for creating and deleting temporary files */ TempFile::TempFile() { } TempFile::~TempFile() { removeAll(); } /*! \brief Create a new temporary file \param ext The extension of the temporary file \returns Path of the new temporary file */ QString TempFile::create(const QString & ext) { QString path = QDir::tempPath()+"/wktemp-"+QUuid::createUuid().toString().mid(1,36)+ext; paths.append(path); return path; } /*! \brief Remove all the temporary files held by this object */ void TempFile::removeAll() { foreach (const QString &path, paths) QFile::remove(path); paths.clear(); } wkhtmltopdf-0.12.5/src/lib/tempfile.hh000066400000000000000000000022611343154624600176360ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __TEMPFILE_HH__ #define __TEMPFILE_HH__ #include #include "dllbegin.inc" class DLL_LOCAL TempFile { private: QStringList paths; public: TempFile(); ~TempFile(); QString create(const QString & ext); void removeAll(); }; #include "dllend.inc" #endif //__TEMPFILE_HH__ wkhtmltopdf-0.12.5/src/lib/tocstylesheet.cc000066400000000000000000000105441343154624600207210ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "outline_p.hh" #include "pdfsettings.hh" #include namespace wkhtmltopdf { void dumpDefaultTOCStyleSheet(QTextStream & stream, settings::TableOfContent & s) { stream << "" << endl << "" << endl << " " << endl << " " << endl << " " << endl << " " << endl << " " << s.captionText << "" << endl << " " << endl << " " << endl << " " << endl << " " << endl << "

" << s.captionText << "

" << endl << "
" << endl << " " << endl << " " << endl << "
" << endl << " " << endl << "
  • " << endl << " " << endl << " " << endl << " " << endl << "
      " << endl << " added to prevent self-closing tags in QtXmlPatterns" << endl << " " << endl << "
    " << endl << "
  • " << endl << "
    " << endl << "
    " << endl; } } wkhtmltopdf-0.12.5/src/lib/utilities.cc000066400000000000000000000166531343154624600200440ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "utilities.hh" #include #include #include #include void loadSvg(QSvgRenderer * & ptr, const QString & path, const char * def, int w, int h) { delete ptr; ptr = 0; if (path != "") { ptr = new QSvgRenderer(path); if (ptr->isValid()) return; qWarning() << "Failed to load " << path; delete ptr; } QByteArray a; QTextStream s(&a, QIODevice::WriteOnly ); s << "\n" << "\n" << "\n" << def << "\n"; s.flush(); ptr = new QSvgRenderer(a); if (ptr->isValid()) return; delete ptr; ptr = 0; } #define RB \ "\n" \ "\n" \ "\n" \ "\n" \ "\n" #define CB \ "\n" \ "\n" \ "\n" \ "\n" \ "\n" \ "\n" \ "\n" \ "\n" \ "\n" void MyLooksStyle::setCheckboxSvg(const QString & path) { loadSvg(checkbox, path, CB, 12, 12); } void MyLooksStyle::setCheckboxCheckedSvg(const QString & path) { loadSvg(checkbox_checked, path, CB "\n", 12, 12); } void MyLooksStyle::setRadioButtonSvg(const QString & path) { loadSvg(radiobutton, path, RB, 11, 11); } void MyLooksStyle::setRadioButtonCheckedSvg(const QString & path) { loadSvg(radiobutton_checked, path, RB "\n", 11, 11); } MyLooksStyle::MyLooksStyle(): weAreDrawingForms(false) { } void MyLooksStyle::producingForms(bool f) {weAreDrawingForms=f;} void MyLooksStyle::drawPrimitive( PrimitiveElement element, const QStyleOption * option, QPainter * painter, const QWidget * widget) const { painter->setBrush(Qt::white); painter->setPen(QPen(Qt::black, 0.7)); painter->setBackground(Qt::NoBrush); painter->setBackgroundMode(Qt::TransparentMode); QRect r = option->rect; if (element == QStyle::PE_PanelLineEdit) { painter->drawRect(r); } else if (element == QStyle::PE_IndicatorCheckBox) { if (weAreDrawingForms || ((option->state & QStyle::State_On)? !checkbox_checked: !checkbox)) { painter->drawRect(r); if (!weAreDrawingForms && (option->state & QStyle::State_On)) { r.translate(int(r.width()*0.075), int(r.width()*0.075)); painter->drawLine(r.topLeft(), r.bottomRight()); painter->drawLine(r.topRight(), r.bottomLeft()); } } else if (option->state & QStyle::State_On) checkbox_checked->render(painter, r); else checkbox->render(painter, r); } else if (element == QStyle::PE_IndicatorRadioButton) { if (weAreDrawingForms || ((option->state & QStyle::State_On)? !radiobutton_checked: !radiobutton)) { painter->drawEllipse(r); if (!weAreDrawingForms && (option->state & QStyle::State_On)) { r.translate(int(r.width()*0.20), int(r.width()*0.20)); r.setWidth(int(r.width()*0.70)); r.setHeight(int(r.height()*0.70)); painter->setBrush(Qt::black); painter->drawEllipse(r); } } else if (option->state & QStyle::State_On) radiobutton_checked->render(painter, r); else radiobutton->render(painter, r); } else { parent_t::drawPrimitive(element, option, painter, widget); } } int handleError(bool success, int errorCode) { QHash cm; cm[400] = "Bad Request"; cm[401] = "Unauthorized"; cm[402] = "Payment Required"; cm[403] = "Forbidden"; cm[404] = "Page not found"; cm[405] = "Method Not Allowed"; cm[500] = "Internal Server Error"; cm[501] = "Not Implemented"; cm[503] = "Service Unavailable"; cm[505] = "HTTP Version Not Supported"; QHash ce; ce[404] = 2; ce[401] = 3; if (errorCode) { int c = EXIT_FAILURE; if (ce.contains(errorCode)) c = ce[errorCode]; const char * m = ""; if (cm.contains(errorCode)) m = cm[errorCode]; if (errorCode < 1000) { fprintf(stderr, "Exit with code %d due to http error: %d %s\n", c, errorCode, m); } else { QNetworkReply::NetworkError error = (QNetworkReply::NetworkError)(errorCode - 1000); QString errorValue; QMetaObject meta = QNetworkReply::staticMetaObject; for (int i=0; i < meta.enumeratorCount(); ++i) { QMetaEnum m = meta.enumerator(i); if (m.name() == QLatin1String("NetworkError")) { errorValue = QLatin1String(m.valueToKey(error)); break; } } fprintf(stderr, "Exit with code %d due to network error: %s\n", c, errorValue.toLocal8Bit().data()); } return c; } else if (!success) { fprintf(stderr, "Exit with code %d, due to unknown error.\n", EXIT_FAILURE); } return success?EXIT_SUCCESS:EXIT_FAILURE; } QSvgRenderer * MyLooksStyle::checkbox = 0; QSvgRenderer * MyLooksStyle::checkbox_checked = 0; QSvgRenderer * MyLooksStyle::radiobutton = 0; QSvgRenderer * MyLooksStyle::radiobutton_checked = 0; wkhtmltopdf-0.12.5/src/lib/utilities.hh000066400000000000000000000036541343154624600200530ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __UTILITIES_HH__ #define __UTILITIES_HH__ #include #include #include #include #include #include #include #include #include /** * Custom simplistic style */ class DLL_PUBLIC MyLooksStyle: public QProxyStyle { Q_OBJECT public: typedef QProxyStyle parent_t; MyLooksStyle(); void drawPrimitive( PrimitiveElement element, const QStyleOption * option, QPainter * painter, const QWidget * widget = 0 ) const; bool weAreDrawingForms; static QSvgRenderer * checkbox; static QSvgRenderer * checkbox_checked; static QSvgRenderer * radiobutton; static QSvgRenderer * radiobutton_checked; public slots: void producingForms(bool f); void setCheckboxSvg(const QString & path); void setCheckboxCheckedSvg(const QString & path); void setRadioButtonSvg(const QString & path); void setRadioButtonCheckedSvg(const QString & path); }; DLL_PUBLIC int handleError(bool success, int errorCode); #include #endif //__UTILITIES_HH__ wkhtmltopdf-0.12.5/src/lib/websettings.cc000066400000000000000000000022671343154624600203630ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "websettings.hh" namespace wkhtmltopdf { namespace settings { Web::Web() : background(true), loadImages(true), enableJavascript(true), enableIntelligentShrinking(true), minimumFontSize(-1), printMediaType(false), defaultEncoding(""), userStyleSheet(""), enablePlugins(false) {} } } wkhtmltopdf-0.12.5/src/lib/websettings.hh000066400000000000000000000033421343154624600203700ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __WEBSETTINGS_HH__ #define __WEBSETTINGS_HH__ #include #include #include namespace wkhtmltopdf { namespace settings { struct DLL_PUBLIC Web { Web(); //! Should we print background images bool background; //! Should we load images bool loadImages; //! Should we enable Javascript bool enableJavascript; //! Should the horrible intelligent shrinking feature be enabled? bool enableIntelligentShrinking; //! Minimum font size int minimumFontSize; //! Should we use the print or the screen media type bool printMediaType; //! Encoding used to enterpit a document with do supplied encoding QString defaultEncoding; //! Stylesheet supplied by the user QString userStyleSheet; //! Should plugins be allowed bool enablePlugins; }; } } #include #endif //__WEBSETTINGS_HH__ wkhtmltopdf-0.12.5/src/pdf/000077500000000000000000000000001343154624600155125ustar00rootroot00000000000000wkhtmltopdf-0.12.5/src/pdf/pdf.pro000066400000000000000000000026441343154624600170130ustar00rootroot00000000000000# Copyright 2010, 2011 wkhtmltopdf authors # # This file is part of wkhtmltopdf. # # wkhtmltopdf is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # wkhtmltopdf is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with wkhtmltopdf. If not, see . include(../../common.pri) TEMPLATE = app TARGET = wkhtmltopdf DESTDIR = ../../bin DEPENDPATH += . ../shared INCLUDEPATH += . ../shared unix { man.path=$$INSTALLBASE/share/man/man1 man.extra=LD_LIBRARY_PATH=../../bin/ ../../bin/wkhtmltopdf --manpage | gzip > $(INSTALL_ROOT)$$INSTALLBASE/share/man/man1/wkhtmltopdf.1.gz QMAKE_EXTRA_TARGETS += man INSTALLS += man } macx { CONFIG -= app_bundle } INSTALLS += target target.path=$$INSTALLBASE/bin include(../shared/shared.pri) CONFIG(shared, shared|static) { LIBS += -L../../bin -lwkhtmltox } else { include(../lib/lib.pri) } #Application part SOURCES += wkhtmltopdf.cc pdfarguments.cc pdfcommandlineparser.cc \ pdfdocparts.cc wkhtmltopdf-0.12.5/src/pdf/pdfarguments.cc000066400000000000000000000335051343154624600205260ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "arghandler.inl" #include "pdfcommandlineparser.hh" #include #include #include /*! \class ArgHandler \brief Class responsible for handling an argument */ /*! \var ArgHandler::longName \brief The long name of the argument, e.g. "help" for "--help" */ /*! \var ArgHandler::desc \brief A descriptive text of the argument */ /*! \var ArgHandler::shortSwitch \brief Sort name, e.g. 'h' for '-h', if 0 there is no short name */ /*! \var ArgHandler::argn \brief The names of the arguments to the switch */ /*! \var ArgHandler::display \brief Indicate that the argument is not hidden */ /*! \var ArgHandler::extended \brief Indicate if the argument is an extended argument */ /*! \var ArgHandler::qthack \brief Indicate that the argument is only available with hacked qt */ /*! \fn ArgHandler::operator()(const char ** args, CommandLineParserPrivate & parser) Callend when the switch was specified \param args The arguments to the switch, guarantied to have size of argn \param settings The settings to store the information in */ /*! \class CommandLineParserPrivate Implementation details for CommandLineParser */ using namespace wkhtmltopdf::settings; struct UnitRealTM: public SomeSetterTM { static UnitReal strToT(const char * val, bool &ok) { return strToUnitReal(val, &ok); } static QString TToStr(const UnitReal & u, bool & ok) { return unitRealToStr(u, &ok); } }; /*! Argument handler setting a real-number/unit combo variable */ typedef SomeSetter UnitRealSetter; struct PageSizeTM: public SomeSetterTM { static QPrinter::PageSize strToT(const char * val, bool &ok) { return strToPageSize(val, &ok); } static QString TToStr(const QPrinter::PageSize & s, bool & ok) { ok=true; return pageSizeToStr(s); } }; /*! Argument handler setting a page size variable */ typedef SomeSetter PageSizeSetter; struct OrientationTM: public SomeSetterTM { static QPrinter::Orientation strToT(const char * val, bool &ok) { return strToOrientation(val, &ok); } static QString TToStr(const QPrinter::Orientation & o, bool & ok) { ok=true; return orientationToStr(o); } }; /*! Argument handler setting a orientation variable */ typedef SomeSetter OrientationSetter; struct DefaultTocFunc { bool operator()(const char **, CommandLineParserBase &, char *) { QFile file; file.open(stdout, QIODevice::WriteOnly | QIODevice::Text); QTextStream stream(&file); wkhtmltopdf::settings::TableOfContent toc; wkhtmltopdf::dumpDefaultTOCStyleSheet(stream, toc); exit(0); } }; /*! Set the default header */ struct DefaultHeaderFunc { bool operator()(const char **, CommandLineParserBase & p, char * page) { reinterpret_cast(page)->header.left="[webpage]"; reinterpret_cast(page)->header.right="[page]/[topage]"; reinterpret_cast(page)->header.line=true; static_cast(p).globalSettings.margin.top = strToUnitReal("2cm"); return true; } }; /*! Setup default book mode */ struct BookFunc { bool operator()(const char **, CommandLineParserBase &) { //p.settings.header.left="[section]"; //p.settings.header.right="[page]/[toPage]"; //p.settings.header.line=true; //p.settings.outline = true; //p.settings.printToc = true; //p.settings.margin.top = Settings::strToUnitReal("2cm"); return true; } }; /*! Construct the commandline parser adding all the arguments \param s The settings to store values in */ PdfCommandLineParser::PdfCommandLineParser(PdfGlobal & s, QList & ps): readArgsFromStdin(false), globalSettings(s), pageSettings(ps) { section("Global Options"); mode(global); addDocArgs(); extended(false); qthack(false); addarg("quiet", 'q', "Be less verbose, maintained for backwards compatibility; Same as using --log-level none", new ConstSetter(s.logLevel, None)); addarg("log-level", 0, "Set log level to: none, error, warn or info", new LogLevelSetter(s.logLevel, "level")); addarg("no-collate", 0, "Do not collate when printing multiple copies", new ConstSetter(s.collate, false)); addarg("collate", 0, "Collate when printing multiple copies", new ConstSetter(s.collate, true)); addarg("copies", 0, "Number of copies to print into the pdf file", new IntSetter(s.copies, "number")); addarg("orientation",'O',"Set orientation to Landscape or Portrait", new OrientationSetter(s.orientation, "orientation")); addarg("page-size",'s',"Set paper size to: A4, Letter, etc.", new PageSizeSetter(s.size.pageSize, "Size")); addarg("grayscale",'g',"PDF will be generated in grayscale", new ConstSetter(s.colorMode,QPrinter::GrayScale)); addarg("lowquality",'l',"Generates lower quality pdf/ps. Useful to shrink the result document space", new ConstSetter(s.resolution,QPrinter::ScreenResolution)); addarg("title", 0, "The title of the generated pdf file (The title of the first document is used if not specified)", new QStrSetter(s.documentTitle,"text")); addarg("read-args-from-stdin", 0, "Read command line arguments from stdin", new ConstSetter(readArgsFromStdin, true) ); extended(true); qthack(false); addarg("margin-bottom",'B',"Set the page bottom margin", new UnitRealSetter(s.margin.bottom,"unitreal")); addarg("margin-left",'L',"Set the page left margin", new UnitRealSetter(s.margin.left,"unitreal")); addarg("margin-right",'R',"Set the page right margin", new UnitRealSetter(s.margin.right,"unitreal")); addarg("margin-top",'T',"Set the page top margin", new UnitRealSetter(s.margin.top,"unitreal")); addarg("dpi",'d',"Change the dpi explicitly (this has no effect on X11 based systems)", new IntSetter(s.dpi,"dpi")); addarg("page-height", 0, "Page height", new UnitRealSetter(s.size.height,"unitreal")); addarg("page-width", 0, "Page width", new UnitRealSetter(s.size.width,"unitreal")); addGlobalLoadArgs(s.load); extended(true); qthack(true); addarg("image-quality", 0, "When jpeg compressing images use this quality", new IntSetter(s.imageQuality,"integer")); addarg("image-dpi", 0, "When embedding images scale them down to this dpi", new IntSetter(s.imageDPI, "integer")); addarg("no-pdf-compression", 0 , "Do not use lossless compression on pdf objects", new ConstSetter(s.useCompression,false)); #ifdef Q_OS_UNIX addarg("use-xserver",0,"Use the X server (some plugins and other stuff might not work without X11)", new ConstSetter(s.useGraphics,true)); #endif section("Outline Options"); extended(true); qthack(true); addarg("outline",0,"Put an outline into the pdf", new ConstSetter(s.outline,true)); addarg("no-outline",0,"Do not put an outline into the pdf", new ConstSetter(s.outline,false)); addarg("outline-depth",0,"Set the depth of the outline", new IntSetter(s.outlineDepth,"level")); addarg("dump-outline",0,"Dump the outline to a file",new QStrSetter(s.dumpOutline,"file")); addarg("dump-default-toc-xsl",0,"Dump the default TOC xsl style sheet to stdout", new Caller()); section("Page Options"); mode(page); addarg("default-header",0,"Add a default header, with the name of the page to the left, and the page number to the right, this is short for: --header-left='[webpage]' --header-right='[page]/[toPage]' --top 2cm --header-line", new Caller()); addarg("viewport-size", 0, "Set viewport size if you have custom scrollbars or css attribute overflow to emulate window size",new QStrSetter(s.viewportSize,"")); addWebArgs(od.web); extended(true); qthack(false); addarg("no-background",0,"Do not print background", new ConstSetter(od.web.background, false)); addarg("background",0,"Do print background", new ConstSetter(od.web.background, true)); extended(true); qthack(true); addarg("include-in-outline", 0, "Include the page in the table of contents and outlines", new ConstSetter(od.includeInOutline, true)); addarg("exclude-from-outline", 0, "Do not include the page in the table of contents and outlines", new ConstSetter(od.includeInOutline, false)); addarg("disable-smart-shrinking", 0, "Disable the intelligent shrinking strategy used by WebKit that makes the pixel/dpi ratio none constant",new ConstSetter(od.web.enableIntelligentShrinking, false)); addarg("enable-smart-shrinking", 0, "Enable the intelligent shrinking strategy used by WebKit that makes the pixel/dpi ratio none constant",new ConstSetter(od.web.enableIntelligentShrinking, true)); extended(false); qthack(true); addarg("print-media-type",0,"Use print media-type instead of screen", new ConstSetter(od.web.printMediaType,true)); addarg("no-print-media-type",0,"Do not use print media-type instead of screen", new ConstSetter(od.web.printMediaType, false)); extended(true); qthack(true); addarg("enable-forms", 0, "Turn HTML form fields into pdf form fields", new ConstSetter(od.produceForms, true)); addarg("disable-forms", 0, "Do not turn HTML form fields into pdf form fields", new ConstSetter(od.produceForms, false)); addarg("disable-internal-links",0,"Do not make local links", new ConstSetter(od.useLocalLinks, false)); addarg("enable-internal-links",0,"Make local links", new ConstSetter(od.useLocalLinks, true)); addarg("disable-external-links",0,"Do not make links to remote web pages", new ConstSetter(od.useExternalLinks, false)); addarg("enable-external-links",0,"Make links to remote web pages", new ConstSetter(od.useExternalLinks, true)); addarg("resolve-relative-links", 0, "Resolve relative external links into absolute links", new ConstSetter(s.resolveRelativeLinks, true)); addarg("keep-relative-links", 0, "Keep relative external links as relative external links", new ConstSetter(s.resolveRelativeLinks, false)); addarg("enable-toc-back-links",0,"Link from section header to toc", new ConstSetter(od.toc.backLinks,true)); addarg("disable-toc-back-links",0,"Do not link from section header to toc", new ConstSetter(od.toc.backLinks,false)); addPageLoadArgs(od.load); addarg("page-offset",0,"Set the starting page number", new IntSetter(s.pageOffset,"offset",1)); section("Headers And Footer Options"); qthack(true); extended(true); addarg("footer-center",0,"Centered footer text", new QStrSetter(od.footer.center,"text")); addarg("footer-font-name",0,"Set footer font name", new QStrSetter(od.footer.fontName,"name"));; addarg("footer-font-size",0,"Set footer font size", new IntSetter(od.footer.fontSize,"size")); addarg("footer-left",0,"Left aligned footer text", new QStrSetter(od.footer.left,"text")); addarg("footer-line",0,"Display line above the footer", new ConstSetter(od.footer.line,true)); addarg("no-footer-line",0,"Do not display line above the footer", new ConstSetter(od.footer.line,false)); addarg("footer-right",0,"Right aligned footer text", new QStrSetter(od.footer.right,"text")); addarg("footer-spacing",0,"Spacing between footer and content in mm", new FloatSetter(od.footer.spacing,"real")); addarg("footer-html",0,"Adds a html footer", new QStrSetter(od.footer.htmlUrl,"url")); addarg("header-center",0,"Centered header text", new QStrSetter(od.header.center,"text")); addarg("header-font-name",0,"Set header font name", new QStrSetter(od.header.fontName,"name")); addarg("header-font-size",0,"Set header font size", new IntSetter(od.header.fontSize,"size")); addarg("header-left",0,"Left aligned header text", new QStrSetter(od.header.left,"text")); addarg("header-line",0,"Display line below the header", new ConstSetter(od.header.line,true)); addarg("no-header-line",0,"Do not display line below the header", new ConstSetter(od.header.line,false)); addarg("header-right",0,"Right aligned header text", new QStrSetter(od.header.right,"text")); addarg("header-spacing",0,"Spacing between header and content in mm", new FloatSetter(od.header.spacing,"real")); addarg("header-html",0,"Adds a html header", new QStrSetter(od.header.htmlUrl,"url")); addarg("replace",0, "Replace [name] with value in header and footer (repeatable)", new MapSetter<>(od.replacements, "name", "value")); section("TOC Options"); mode(toc); extended(true); qthack(true); addarg("xsl-style-sheet",0,"Use the supplied xsl style sheet for printing the table of content", new QStrSetter(od.tocXsl,"file")); addarg("toc-header-text",0,"The header text of the toc", new QStrSetter(od.toc.captionText, "text")); addarg("disable-toc-links",0,"Do not link from toc to sections", new ConstSetter(od.toc.forwardLinks, false)); addarg("disable-dotted-lines",0,"Do not use dotted lines in the toc", new ConstSetter(od.toc.useDottedLines,false)); addarg("toc-text-size-shrink",0,"For each level of headings in the toc the font is scaled by this factor", new FloatSetter(od.toc.fontScale, "real")); addarg("toc-level-indentation",0,"For each level of headings in the toc indent by this length", new QStrSetter(od.toc.indentation, "width")); } wkhtmltopdf-0.12.5/src/pdf/pdfcommandlineparser.cc000066400000000000000000000135421343154624600222230ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "outputter.hh" #include "pdfcommandlineparser.hh" #include using namespace wkhtmltopdf::settings; /*! \file commandlineparser.hh \brief Defines the PdfCommandLineParser class */ /*! \file commandlineparser_p.hh \brief Defines the PdfCommandLineParserPrivate, ArgHandler and Outputter class */ /*! Output the man page to a given file \param fd The file to store the man page */ void PdfCommandLineParser::manpage(FILE * fd) const { Outputter * o = Outputter::man(fd); outputManName(o); outputSynopsis(o); outputDescripton(o); outputSwitches(o, true, false); outputProxyDoc(o); #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ outputHeaderFooterDoc(o); outputOutlineDoc(o); outputTableOfContentDoc(o); #else outputNotPatched(o,true); #endif outputPageSizes(o); outputArgsFromStdin(o); outputPageBreakDoc(o); outputContact(o); outputAuthors(o); delete o; } /*! Output usage information aka. --help \param fd The file to output the information to \param extended Should we show extended arguments */ void PdfCommandLineParser::usage(FILE * fd, bool extended) const { Outputter * o = Outputter::text(fd,false); outputName(o); outputSynopsis(o); outputDescripton(o); outputSwitches(o, extended, false); #ifndef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ outputNotPatched(o, true); #endif if (extended) { outputPageSizes(o); outputArgsFromStdin(o); outputProxyDoc(o); outputHeaderFooterDoc(o); outputOutlineDoc(o); outputTableOfContentDoc(o); } outputContact(o); delete o; } /*! Output the readme/manual \param fd The file to output to \param html Do we want the html manual, or the README */ void PdfCommandLineParser::readme(FILE * fd, bool html) const { Outputter * o = html?Outputter::html(fd):Outputter::text(fd, true); outputDocStart(o); outputContact(o); outputNotPatched(o, false); outputLicense(o); outputAuthors(o); outputSynopsis(o); outputSwitches(o, true, true); outputProxyDoc(o); outputHeaderFooterDoc(o); outputOutlineDoc(o); outputTableOfContentDoc(o); outputPageBreakDoc(o); outputPageSizes(o); outputArgsFromStdin(o); outputStaticProblems(o); outputInstallation(o); outputExamples(o); delete o; } /*! * Load default arguments and put them in the settings structure */ //void PdfCommandLineParser::loadDefaults() { //settings.in.clear(); //settings.proxy.host = ""; //foreach(ArgHandler * h, longToHandler) // h->useDefault(*d); //Load configuration from environment //char * val; //const char * vars[] = {"proxy","all_proxy","http_proxy", NULL}; //for(int i=0; vars[i]; ++i) { // if ((val = getenv("proxy"))) { // bool ok=false; // Settings::ProxySettings p = Settings::strToProxy(val, &ok); // if (ok) // settings.proxy = p; // } //} //} /*! * Parse command line arguments, and set settings accordingly. * \param argc the number of command line arguments * \param argv a NULL terminated list with the arguments */ void PdfCommandLineParser::parseArguments(int argc, const char ** argv, bool fromStdin) { bool defaultMode = false; int arg=1; PdfObject def; //Parse global options for (;arg < argc;++arg) { if (argv[arg][0] != '-' || argv[arg][1] == '\0' || defaultMode) break; parseArg(global | page, argc, argv, defaultMode, arg, (char *)&def); } if (readArgsFromStdin && !fromStdin) return; //Parse page options while (arg < argc-1) { pageSettings.push_back(def); PdfObject & ps = pageSettings.back(); int sections = page; if (!strcmp(argv[arg],"cover")) { ++arg; if (arg >= argc-1) { fprintf(stderr, "You need to specify a input file to cover\n\n"); usage(stderr, false); exit(1); } ps.page = QString::fromLocal8Bit(argv[arg++]); // parse page options and then override the header/footer settings for (;arg < argc;++arg) { if (argv[arg][0] != '-' || argv[arg][1] == '\0' || defaultMode) break; parseArg(sections, argc, argv, defaultMode, arg, (char*)&ps); } ps.header.left = ps.header.right = ps.header.center = ""; ps.footer.left = ps.footer.right = ps.footer.center = ""; ps.header.line = ps.footer.line = false; ps.header.htmlUrl = ps.footer.htmlUrl = ""; ps.includeInOutline = false; continue; } else if (!strcmp(argv[arg],"toc")) { ++arg; sections = page | toc; ps.isTableOfContent = true; } else { if (!strcmp(argv[arg],"page")) { ++arg; if (arg >= argc-1) { fprintf(stderr, "You need to specify a input file to page\n\n"); usage(stderr, false); exit(1); } } QByteArray a(argv[arg]); ps.page = QString::fromLocal8Bit(a); ++arg; } for (;arg < argc;++arg) { if (argv[arg][0] != '-' || argv[arg][1] == '\0' || defaultMode) break; parseArg(sections, argc, argv, defaultMode, arg, (char*)&ps); } } if (pageSettings.size() == 0 || argc < 2) { fprintf(stderr, "You need to specify at least one input file, and exactly one output file\nUse - for stdin or stdout\n\n"); usage(stderr, false); exit(1); } globalSettings.out = QString::fromLocal8Bit(argv[argc-1]); } wkhtmltopdf-0.12.5/src/pdf/pdfcommandlineparser.hh000066400000000000000000000053201343154624600222300ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __PDFCOMMANDLINEPARSER_HH__ #define __PDFCOMMANDLINEPARSER_HH__ #include "commandlineparserbase.hh" #include #include class PdfCommandLineParser: public CommandLineParserBase { public: const static int global = 1; const static int page = 2; const static int toc = 4; bool readArgsFromStdin; wkhtmltopdf::settings::PdfGlobal & globalSettings; QList & pageSettings; wkhtmltopdf::settings::PdfObject od; //Arguments.cc PdfCommandLineParser(wkhtmltopdf::settings::PdfGlobal & globalSettings, QList & pageSettings); //docparts.cc void outputManName(Outputter * o) const; void outputSynopsis(Outputter * o) const; void outputDescripton(Outputter * o) const; void outputPageSizes(Outputter * o) const; void outputArgsFromStdin(Outputter * o) const; void outputHeaderFooterDoc(Outputter * o) const; void outputTableOfContentDoc(Outputter * o) const; void outputOutlineDoc(Outputter * o) const; void outputNotPatched(Outputter * o, bool sure) const; void outputPageBreakDoc(Outputter * o) const; void outputContact(Outputter * o) const; void outputDocStart(Outputter * o) const; void outputInstallation(Outputter * o) const; void outputExamples(Outputter * o) const; //commandlineparser.cc virtual QString appName() const {return "wkhtmltopdf";} virtual void usage(FILE * fd, bool extended) const; virtual void manpage(FILE * fd) const; virtual void readme(FILE * fd, bool html) const; void parseArguments(int argc, const char ** argv, bool fromStdin=false); virtual char * mapAddress(char * d, char * ns) const { const char * _od = reinterpret_cast(&od); if (_od > d || d >= _od + sizeof(wkhtmltopdf::settings::PdfObject)) return d;; return d - _od + ns; } }; #endif //__PDFCOMMANDLINEPARSER_HH__ wkhtmltopdf-0.12.5/src/pdf/pdfdocparts.cc000066400000000000000000000426511343154624600203420ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "outputter.hh" #include "pdfcommandlineparser.hh" #include #define STRINGIZE_(x) #x #define STRINGIZE(x) STRINGIZE_(x) /*! Output name and a short description \param o The outputter to output to */ void PdfCommandLineParser::outputManName(Outputter * o) const { o->beginSection("Name"); o->paragraph("wkhtmltopdf - html to pdf converter"); o->endSection(); } /*! Output a short synopsis on how to call the command line program \param o The outputter to output to */ void PdfCommandLineParser::outputSynopsis(Outputter * o) const { o->beginSection("Synopsis"); o->verbatim("wkhtmltopdf [GLOBAL OPTION]... [OBJECT]... \n"); o->endSection(); o->beginSection("Document objects"); o->beginParagraph(); o->text("wkhtmltopdf is able to put several objects into the output file, an object is either " "a single webpage, a cover webpage or a table of contents. The objects are put into " "the output document in the order they are specified on the command line, options can " "be specified on a per object basis or in the global options area. Options from the "); o->sectionLink("Global Options"); o->text(" section can only be placed in the global options area"); o->endParagraph(); o->paragraph("A page objects puts the content of a single webpage into the output document."); o->verbatim("(page)? [PAGE OPTION]..."); o->beginParagraph(); o->text("Options for the page object can be placed in the global options and the page " "options areas. The applicable options can be found in the "); o->sectionLink("Page Options"); o->text(" and "); o->sectionLink("Headers And Footer Options"); o->text(" sections."); o->endParagraph(); o->paragraph("A cover objects puts the content of a single webpage into the output document, " "the page does not appear in the table of contents, and does not have headers and footers."); o->verbatim("cover [PAGE OPTION]..."); o->paragraph("All options that can be specified for a page object can also be specified for a cover."); o->paragraph("A table of contents object inserts a table of contents into the output document."); o->verbatim("toc [TOC OPTION]..."); o->beginParagraph(); o->text("All options that can be specified for a page object can also be specified for a toc, " "further more the options from the "); o->sectionLink("TOC Options"); o->text(" section can also be applied. The table of contents is generated via XSLT which means " "that it can be styled to look however you want it to look. To get an idea of how to " "do this you can dump the default xslt document by supplying the --dump-default-toc-xsl, and the outline it works on by supplying --dump-outline, see the "); o->sectionLink("Outline Options"); o->text(" section."); o->endParagraph(); o->endSection(); } /*! Explain what the program does \param o The outputter to output to */ void PdfCommandLineParser::outputDescripton(Outputter * o) const { o->beginSection("Description"); o->beginParagraph(); o->text("Converts one or more HTML pages into a PDF document, "); #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ o->text("using wkhtmltopdf patched qt."); #else o->bold("not"); o->text(" using wkhtmltopdf patched qt."); #endif o->endParagraph(); o->endSection(); } /*! Add explanation about reduced functionality without patched qt/webkit \param o The outputter to output to \param sure Is the functionality restricted in this wkhtmltopdf */ void PdfCommandLineParser::outputNotPatched(Outputter * o, bool sure) const { o->beginSection("Reduced Functionality"); if (sure) o->paragraph("This version of wkhtmltopdf has been compiled against a version of " "QT without the wkhtmltopdf patches. Therefore some features are missing, " "if you need these features please use the static version."); else o->paragraph("Some versions of wkhtmltopdf are compiled against a version of QT " "without the wkhtmltopdf patches. These versions are missing some features, " "you can find out if your version of wkhtmltopdf is one of these by running wkhtmltopdf --version " "if your version is against an unpatched QT, you can use the static version to get all functionality."); o->paragraph("Currently the list of features only supported with patch QT includes:"); o->beginList(); o->listItem("Printing more than one HTML document into a PDF file."); o->listItem("Running without an X11 server."); o->listItem("Adding a document outline to the PDF file."); o->listItem("Adding headers and footers to the PDF file."); o->listItem("Generating a table of contents."); o->listItem("Adding links in the generated PDF file."); o->listItem("Printing using the screen media-type."); o->listItem("Disabling the smart shrink feature of WebKit."); o->endList(); o->endSection(); } /*! Explain the page breaking is somewhat broken \param o The outputter to output to */ void PdfCommandLineParser::outputPageBreakDoc(Outputter * o) const { o->beginSection("Page Breaking"); o->paragraph( "The current page breaking algorithm of WebKit leaves much to be desired. " "Basically WebKit will render everything into one long page, and then cut it up " "into pages. This means that if you have two columns of text where one is " "vertically shifted by half a line. Then WebKit will cut a line into to pieces " "display the top half on one page. And the bottom half on another page. " "It will also break image in two and so on. If you are using the patched version of " "QT you can use the CSS page-break-inside property to remedy this somewhat. " "There is no easy solution to this problem, until this is solved try organizing " "your HTML documents such that it contains many lines on which pages can be cut " "cleanly."); o->endSection(); } /*! Output documentation about headers and footers \param o The outputter to output to */ void PdfCommandLineParser::outputHeaderFooterDoc(Outputter * o) const { o->beginSection("Footers And Headers"); o->paragraph("Headers and footers can be added to the document by the --header-* and --footer* " "arguments respectfully. In header and footer text string supplied to e.g. --header-left, " "the following variables will be substituted."); o->verbatim( " * [page] Replaced by the number of the pages currently being printed\n" " * [frompage] Replaced by the number of the first page to be printed\n" " * [topage] Replaced by the number of the last page to be printed\n" " * [webpage] Replaced by the URL of the page being printed\n" " * [section] Replaced by the name of the current section\n" " * [subsection] Replaced by the name of the current subsection\n" " * [date] Replaced by the current date in system local format\n" " * [isodate] Replaced by the current date in ISO 8601 extended format\n" " * [time] Replaced by the current time in system local format\n" " * [title] Replaced by the title of the of the current page object\n" " * [doctitle] Replaced by the title of the output document\n" " * [sitepage] Replaced by the number of the page in the current site being converted\n" " * [sitepages] Replaced by the number of pages in the current site being converted\n" "\n"); o->paragraph("As an example specifying --header-right \"Page [page] of [toPage]\", " "will result in the text \"Page x of y\" where x is the number of the " "current page and y is the number of the last page, to appear in the upper " "left corner in the document."); o->paragraph("Headers and footers can also be supplied with HTML documents. As an example one " "could specify --header-html header.html, and use the following content in header.html:"); o->verbatim( "\n" "\n" "\n" " \n" " \n" " \n" " \n" "
    \n" " Page of \n" "
    \n" "\n" "\n" ); o->paragraph("As can be seen from the example, the arguments are sent to the header/footer " "html documents in get fashion."); o->endSection(); } void PdfCommandLineParser::outputTableOfContentDoc(Outputter * o) const { o->beginSection("Table Of Contents"); o->paragraph("A table of contents can be added to the document by adding a toc object " "to the command line. For example:"); o->verbatim("wkhtmltopdf toc http://qt-project.org/doc/qt-4.8/qstring.html qstring.pdf\n"); o->paragraph("The table of contents is generated based on the H tags in the input " "documents. First a XML document is generated, then it is converted to " "HTML using XSLT."); o->paragraph("The generated XML document can be viewed by dumping it to a file using " "the --dump-outline switch. For example:"); o->verbatim("wkhtmltopdf --dump-outline toc.xml http://qt-project.org/doc/qt-4.8/qstring.html qstring.pdf\n"); o->paragraph("The XSLT document can be specified using the --xsl-style-sheet switch. " "For example:"); o->verbatim("wkhtmltopdf toc --xsl-style-sheet my.xsl http://qt-project.org/doc/qt-4.8/qstring.html qstring.pdf\n"); o->paragraph("The --dump-default-toc-xsl switch can be used to dump the default " "XSLT style sheet to stdout. This is a good start for writing your " "own style sheet"); o->verbatim("wkhtmltopdf --dump-default-toc-xsl"); o->paragraph("The XML document is in the namespace " "\"http://wkhtmltopdf.org/outline\" " "it has a root node called \"outline\" which contains a number of " "\"item\" nodes. An item can contain any number of item. These are the " "outline subsections to the section the item represents. A item node " "has the following attributes:"); o->beginList(); o->listItem("\"title\" the name of the section."); o->listItem("\"page\" the page number the section occurs on."); o->listItem("\"link\" a URL that links to the section."); o->listItem("\"backLink\" the name of the anchor the section will link back to."); o->endList(); o->paragraph("The remaining TOC options only affect the default style sheet " "so they will not work when specifying a custom style sheet."); o->endSection(); } /*! Output documentation about outlines \param o The outputter to output to */ void PdfCommandLineParser::outputOutlineDoc(Outputter * o) const { o->beginSection("Outlines"); o->beginParagraph(); o->text( "Wkhtmltopdf with patched qt has support for PDF outlines also known as " "book marks, this can be enabled by specifying the --outline switch. " "The outlines are generated based on the tags, for a in-depth " "description of how this is done see the "); o->sectionLink("Table Of Contents"); o->text(" section. "); o->endParagraph(); o->paragraph( "The outline tree can sometimes be very deep, if the tags where " "spread to generous in the HTML document. The --outline-depth switch can " "be used to bound this."); o->endSection(); } /*! Output contact information \param o The outputter to output to */ void PdfCommandLineParser::outputContact(Outputter * o) const { o->beginSection("Contact"); o->beginParagraph(); o->text("If you experience bugs or want to request new features please visit "); o->link("https://github.com/wkhtmltopdf/wkhtmltopdf/issues"); o->endParagraph(); o->endSection(); } /*! Output beginning of the readme \param o The outputter to output to */ void PdfCommandLineParser::outputDocStart(Outputter * o) const { o->beginSection("wkhtmltopdf " STRINGIZE(FULL_VERSION) " Manual"); o->paragraph("This file documents wkhtmltopdf, a program capable of converting html " "documents into PDF documents."); o->endSection(); } /*! Output information on how to use read-args-from-stdin \param o The outputter to output to */ void PdfCommandLineParser::outputArgsFromStdin(Outputter * o) const { o->beginSection("Reading arguments from stdin"); o->paragraph("If you need to convert a lot of pages in a batch, and you feel that wkhtmltopdf " "is a bit too slow to start up, then you should try --read-args-from-stdin,"); o->paragraph("When --read-args-from-stdin each line of input sent to wkhtmltopdf on stdin " "will act as a separate invocation of wkhtmltopdf, with the arguments specified " "on the given line combined with the arguments given to wkhtmltopdf"); o->paragraph("For example one could do the following:"); o->verbatim("echo \"http://qt-project.org/doc/qt-4.8/qapplication.html qapplication.pdf\" >> cmds\n" "echo \"cover google.com http://en.wikipedia.org/wiki/Qt_(software) qt.pdf\" >> cmds\n" "wkhtmltopdf --read-args-from-stdin --book < cmds\n"); o->endSection(); } /*! Output information on how to install \param o The outputter to output to */ void PdfCommandLineParser::outputInstallation(Outputter * o) const { o->beginSection("Installation"); o->paragraph( "There are several ways to install wkhtmltopdf. You can download a " "already compiled binary, or you can compile wkhtmltopdf yourself. " "On windows the easiest way to install wkhtmltopdf is to download " "the latest installer. On Linux you can download the latest static " "binary, however you still need to install some other pieces of " "software, to learn more about this read the static version section " "of the manual."); o->endSection(); } /*! Output documentation about page sizes \param o The outputter to output to */ void PdfCommandLineParser::outputPageSizes(Outputter * o) const { o->beginSection("Page sizes"); o->beginParagraph(); o->text("The default page size of the rendered document is A4, but using this --page-size option" "this can be changed to almost anything else, such as: A3, Letter and Legal. " "For a full list of supported pages sizes please see "); o->link("http://qt-project.org/doc/qt-4.8/qprinter.html#PaperSize-enum"); o->text("."); o->endParagraph(); o->paragraph("For a more fine grained control over the page size the " "--page-height and --page-width options may be used"); o->endSection(); } /*! Output examples on how to use wkhtmltopdf \param o The outputter to output to */ void PdfCommandLineParser::outputExamples(Outputter * o) const { o->beginSection("Examples"); o->paragraph("This section presents a number of examples of how to invoke wkhtmltopdf."); o->paragraph("To convert a remote HTML file to PDF:"); o->verbatim("wkhtmltopdf http://www.google.com google.pdf\n"); o->paragraph("To convert a local HTML file to PDF:"); o->verbatim("wkhtmltopdf my.html my.pdf\n"); o->paragraph("Produce the eler2.pdf sample file:"); o->verbatim("wkhtmltopdf -H http://geekz.co.uk/lovesraymond/archive/eler-highlights-2008 eler2.pdf\n"); o->paragraph("Printing a book with a table of contents:"); o->verbatim("wkhtmltopdf -H cover cover.html toc chapter1.html chapter2.html chapter3.html book.pdf\n"); o->endSection(); } // LocalWords: webkit bool unpatched beginList listItem endList WebKit http // LocalWords: stroustrup wkhtmltopdf commandlineparser hh QWebFrame param px // LocalWords: STRINGIZE outputter const beginSection beginParagraph QString // LocalWords: ifdef endif endParagraph endSection GPLv GPL Truelsen Mário td // LocalWords: Bouthenot PDF CSS username BNF frompage topage webpage toPage // LocalWords: html subst unescape subsubsection getElementsByClassName args // LocalWords: textContent onload readme stdin qapplication pdf cmds google // LocalWords: todo gcc openssl sudo dep libqt gui xorg wget xvf svn linux ps // LocalWords: PageSize enum eler glibc xserver xfonts libssl dev wkhtml cd // LocalWords: nomake opensource xslt wkhtmltopdf-0.12.5/src/pdf/wkhtmltopdf.cc000066400000000000000000000164761343154624600204020ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "pdfcommandlineparser.hh" #include "progressfeedback.hh" #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(Q_OS_UNIX) #include #endif using namespace wkhtmltopdf::settings; using namespace wkhtmltopdf; /*! * State mashine driven, shell like parser. This is used for * reading commandline options from stdin * \param buff the line to parse * \param nargc on return will hold the number of arguments read * \param nargv on return will hold the arguments read and be NULL terminated */ enum State {skip, tok, q1, q2, q1_esc, q2_esc, tok_esc}; void parseString(char * buff, int &nargc, char ***nargv) { int nargv_size = 1024; *nargv = (char**)malloc(sizeof(char*) * nargv_size); if (!*nargv) exit(1); State state = skip; int write_start=0; int write=0; for (int read=0; buff[read]!='\0'; ++read) { State next_state=state; switch (state) { case skip: //Whitespace skipping state if (buff[read]!=' ' && buff[read]!='\t' && buff[read]!='\r' && buff[read]!='\n') { --read; next_state=tok; } break; case tok: //Normal toking reading state if (buff[read]=='\'') next_state=q1; else if (buff[read]=='"') next_state=q2; else if (buff[read]=='\\') next_state=tok_esc; else if (buff[read]==' ' || buff[read]=='\t' || buff[read]=='\n' || buff[read]=='\r') { next_state=skip; if (write_start != write) { buff[write++]='\0'; if (nargc+1 >= nargv_size) { nargv_size *= 2; *nargv = (char**)realloc(*nargv, sizeof(char*) * nargv_size); if (!*nargv) exit(1); } (*nargv)[nargc++] = buff+write_start; } write_start = write; } else buff[write++] = buff[read]; break; case q1: //State parsing a single qoute argument if (buff[read]=='\'') next_state=tok; else if (buff[read]=='\\') next_state=q1_esc; else buff[write++] = buff[read]; break; case q2: //State parsing a double qoute argument if (buff[read]=='"') next_state=tok; else if (buff[read]=='\\') next_state=q2_esc; else buff[write++] = buff[read]; break; case tok_esc: //Escape one char and return to the token parsing state next_state=tok; buff[write++] = buff[read]; break; case q1_esc: //Espace one char and return to the single quote parsing state next_state=q1; buff[write++] = buff[read]; break; case q2_esc: //Escape one char and return to the double qoute parsing state next_state=q2; buff[write++] = buff[read]; break; } state=next_state; } if (nargc+1 + 2 >= nargv_size) { nargv_size *= 2; *nargv = (char**)realloc(*nargv, sizeof(char*) * nargv_size); if (!*nargv) exit(1); } //Remember the last parameter if (write_start != write) { buff[write++]='\0'; (*nargv)[nargc++] = buff+write_start; } (*nargv)[nargc]=NULL; } /* * Returns a line from a FILE stream. Caller must free buffer. * Derived from getline function from DHCPD client daemon. * Needed because of Windows and systems before POSIX 2008. */ char * fgets_large(FILE * fp) { const size_t bufsize_grow = 1024; size_t bytes = 0, buflen = 0; char *p, *buf = NULL; do { if (feof(fp)) break; if (buf == NULL || bytes != 0) { buflen += bufsize_grow; buf = (char *)realloc(buf, buflen); if (buf == NULL) return NULL; } p = buf + bytes; memset(p, 0, bufsize_grow); if (fgets(p, bufsize_grow, fp) == NULL) break; bytes += strlen(p); } while (bytes == 0 || *(buf + (bytes - 1)) != '\n'); if (bytes == 0) return NULL; return buf; } int main(int argc, char * argv[]) { #if defined(Q_OS_UNIX) setlocale(LC_ALL, ""); #if QT_VERSION >= 0x050000 && !defined(__EXTENSIVE_WKHTMLTOPDF_QT_HACK__) setenv("QT_QPA_PLATFORM", "offscreen", 0); #endif #endif //This will store all our settings PdfGlobal globalSettings; QList objectSettings; //Create a command line parser to parse commandline arguments PdfCommandLineParser parser(globalSettings, objectSettings); //Setup default values in settings //parser.loadDefaults(); //Parse the arguments parser.parseArguments(argc, (const char**)argv); //Construct QApplication required for printing bool use_graphics=true; #if defined(Q_OS_UNIX) || defined(Q_OS_MAC) #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ use_graphics=globalSettings.useGraphics; if (!use_graphics) QApplication::setGraphicsSystem("raster"); #endif #endif QApplication a(argc, argv, use_graphics); MyLooksStyle * style = new MyLooksStyle(); a.setStyle(style); if (parser.readArgsFromStdin) { char *buff; while ((buff = fgets_large(stdin)) != NULL) { int nargc=argc; char **nargv; parseString(buff,nargc,&nargv); for (int i=0; i < argc; ++i) nargv[i] = argv[i]; PdfGlobal globalSettings; QList objectSettings; //Create a command line parser to parse commandline arguments PdfCommandLineParser parser(globalSettings, objectSettings); //Setup default values in settings //parser.loadDefaults(); //Parse the arguments parser.parseArguments(nargc, (const char**)nargv, true); PdfConverter converter(globalSettings); ProgressFeedback feedback(globalSettings.logLevel, converter); foreach (const PdfObject & object, objectSettings) converter.addResource(object); if (!converter.convert()) exit(EXIT_FAILURE); free(buff); free(nargv); } exit(EXIT_SUCCESS); } //Create the actual page converter to convert the pages PdfConverter converter(globalSettings); QObject::connect(&converter, SIGNAL(producingForms(bool)), style, SLOT(producingForms(bool))); QObject::connect(&converter, SIGNAL(checkboxSvgChanged(const QString &)), style, SLOT(setCheckboxSvg(const QString &))); QObject::connect(&converter, SIGNAL(checkboxCheckedSvgChanged(const QString &)), style, SLOT(setCheckboxCheckedSvg(const QString &))); QObject::connect(&converter, SIGNAL(radiobuttonSvgChanged(const QString &)), style, SLOT(setRadioButtonSvg(const QString &))); QObject::connect(&converter, SIGNAL(radiobuttonCheckedSvgChanged(const QString &)), style, SLOT(setRadioButtonCheckedSvg(const QString &))); ProgressFeedback feedback(globalSettings.logLevel, converter); foreach (const PdfObject & object, objectSettings) converter.addResource(object); bool success = converter.convert(); return handleError(success, converter.httpErrorCode()); } wkhtmltopdf-0.12.5/src/shared/000077500000000000000000000000001343154624600162075ustar00rootroot00000000000000wkhtmltopdf-0.12.5/src/shared/arghandler.cc000066400000000000000000000022231343154624600206240ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "outputter.hh" /*! \fn ArgHandler::getDesc() const Get the description of this switch */ QString ArgHandler::getDesc() const { return desc; } /*! \fn ArgHandlerBase::~ArgHandlerBase() Dummy virtual destructor */ ArgHandler::~ArgHandler() {} wkhtmltopdf-0.12.5/src/shared/arghandler.inl000066400000000000000000000137001343154624600210230ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __ARGHANDLER_INL__ #define __ARGHANDLER_INL__ #include "commandlineparserbase.hh" #include #include template class DstArgHandler: public ArgHandler { public: T & dst; DstArgHandler(T & d): dst(d) {}; T & realDst(const CommandLineParserBase & cp, char * page) { return * reinterpret_cast(cp.mapAddress(reinterpret_cast(&dst), page)); } }; /*! Sets a variable to some constant */ template class ConstSetter: public DstArgHandler { public: typedef DstArgHandler p_t; const T src; ConstSetter(T & arg, const T s): p_t(arg), src(s) {}; bool operator() (const char **, CommandLineParserBase & cp, char * ps) { p_t::realDst(cp, ps)=src; return true; } virtual QString getDesc() const { if (src != p_t::dst) return p_t::desc; return p_t::desc + " (default)"; } }; struct StringPairCreator { typedef QPair T; inline T operator()(const QString & key, const QString & value) const { return T(key, value); } }; template struct PostItemCreator { typedef wkhtmltopdf::settings::PostItem T; inline T operator()(const QString & key, const QString & value) const { T p; p.name = key; p.value = value; p.file = file; return p; } }; /*! Putting values into a map */ template struct MapSetter: public DstArgHandler< QList< typename T::T > > { typedef DstArgHandler > p_t; MapSetter(QList & a, QString keyName, QString valueName) : p_t(a) { p_t::argn.push_back(keyName); p_t::argn.push_back(valueName); } virtual bool operator() (const char ** args, CommandLineParserBase & cp, char * ps) { p_t::realDst(cp, ps).append( T()(args[0], args[1]) ); return true; } }; struct StringListSetter: public DstArgHandler > { typedef DstArgHandler > p_t; StringListSetter(QList & a, QString valueName) : p_t (a) { p_t::argn.push_back(valueName); } virtual bool operator() (const char ** args, CommandLineParserBase & cp, char * ps) { p_t::realDst(cp, ps).append( args[0] ); return true; } }; /*! SomeSetter template method base */ template struct SomeSetterTM { typedef TT T; //T strToT(const char * val, bool & ok); static QString TToStr(const T &, bool & ok) {ok=false; return "";} }; /*! TemplateMethod class used to set a single variable of some type TT::T */ template struct SomeSetter: public DstArgHandler { typedef DstArgHandler p_t; typedef typename TT::T T; bool hasDef; SomeSetter(T & a, QString an, bool def=true): p_t(a), hasDef(def) { p_t::argn.push_back(an); } bool operator() (const char ** vals, CommandLineParserBase & cp, char * ps) { bool ok; p_t::realDst(cp, ps) = TT::strToT(vals[0], ok); return ok; } virtual QString getDesc() const { if (!hasDef) return p_t::desc; bool ok; QString x = TT::TToStr(p_t::dst, ok); if (!ok) return p_t::desc; return p_t::desc + " (default " + x + ")"; } }; struct IntTM: public SomeSetterTM { static int strToT(const char * val, bool & ok) { return QString(val).toInt(&ok); } static QString TToStr(const int & t, bool & ok) { ok=(t!=-1); return QString::number(t); } }; /*! Argument handler setting an int variable */ typedef SomeSetter IntSetter; struct FloatTM: public SomeSetterTM { static float strToT(const char * val, bool & ok) { return QString(val).toFloat(&ok); } static QString TToStr(const float & t, bool & ok) { ok=(t!=-1); return QString::number(t); } }; /*! Argument handler setting an float variable */ typedef SomeSetter FloatSetter; struct LogLevelTM: public SomeSetterTM { static wkhtmltopdf::settings::LogLevel strToT(const char * val, bool & ok) { return wkhtmltopdf::settings::strToLogLevel(val, &ok); } static QString TToStr(const wkhtmltopdf::settings::LogLevel & l, bool & ok) { return wkhtmltopdf::settings::logLevelToStr(l, &ok); } }; /*! Argument handler setting an loglevel variable */ typedef SomeSetter LogLevelSetter; struct StrTM: public SomeSetterTM { static const char * strToT(const char * val, bool & ok) { ok=true; return val; } static QString TToStr(const char * t, bool & ok) { ok = (t[0] != '\0'); return QString(t); } }; /*! Argument handler setting a string variable */ typedef SomeSetter StrSetter; struct QStrTM: public SomeSetterTM { static QString strToT(const char * val, bool & ok) { ok=true; return QString::fromLocal8Bit(val); } static QString TToStr(const QString & t, bool & ok) { ok=!t.isEmpty(); return t; } }; /*! Argument handler setting a string variable */ typedef SomeSetter QStrSetter; /*! Argument handler responsible for calling a function */ template struct Caller: public ArgHandler { Caller() {} Caller(QString a1) { argn.push_back(a1); } bool operator() (const char **vals, CommandLineParserBase & s, char * page) { return T()(vals, s, page); } }; #endif //__ARGHANDLER_INL__ wkhtmltopdf-0.12.5/src/shared/commandlineparserbase.cc000066400000000000000000000132261343154624600230600ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "commandlineparserbase.hh" #include "outputter.hh" #include bool ahsort(const ArgHandler * a, const ArgHandler * b) { QRegExp e("^(no|enable|disable|include-in|exclude-from)-"); QString x=a->longName; QString y=b->longName; x.remove(e); y.remove(e); if (x == y) { QRegExp e("^no-"); x=a->longName; y=b->longName; x.replace(e,"zzzz"); y.replace(e,"zzzz"); } return x < y; } /*! Output description of switches to an outputter \param o The outputter to output to \param extended Should we also output extended arguments \param doc Indicate to the outputter that it is writing documentation */ void CommandLineParserBase::outputSwitches(Outputter * o, bool extended, bool doc) const { foreach (const QString & section, sections) { QList display; foreach (const ArgHandler * handler, sectionArgumentHandles[section]) { #ifndef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ if (!doc && handler->qthack) continue; #else Q_UNUSED(doc); #endif if (!extended && handler->extended) continue; display.push_back(handler); } qSort(display.begin(), display.end(), ahsort); if (display.size() == 0) continue; o->beginSection(section); if (!sectionDesc[section].isEmpty()) { o->beginParagraph(); o->text(sectionDesc[section]); o->endParagraph(); } o->beginSwitch(); foreach (const ArgHandler * handler, display) o->cswitch(handler); o->endSwitch(); o->endSection(); } } #define STRINGIZE_(x) #x #define STRINGIZE(x) STRINGIZE_(x) const char *CommandLineParserBase::appVersion() const { #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ return STRINGIZE(FULL_VERSION) " (with patched qt)"; #else return STRINGIZE(FULL_VERSION); #endif } /*! Output version information aka. --version \param fd The file to output to */ void CommandLineParserBase::version(FILE * fd) const { fprintf(fd, "%s %s\n", appName().toLocal8Bit().constData(), appVersion()); } /*! Output license information aka. --license \param fd The file to output to */ void CommandLineParserBase::license(FILE * fd) const { Outputter * o = Outputter::text(fd,false); outputName(o); outputAuthors(o); outputLicense(o); delete o; } void CommandLineParserBase::parseArg(int sections, const int argc, const char ** argv, bool & defaultMode, int & arg, char * page) { if (argv[arg][1] == '-') { //We have a long style argument //After an -- apperas in the argument list all that follows is interpreted as default arguments if (argv[arg][2] == '0') { defaultMode=true; return; } //Try to find a handler for this long switch QHash::iterator j = longToHandler.find(argv[arg]+2); if (j == longToHandler.end()) { //Ups that argument did not exist fprintf(stderr, "Unknown long argument %s\n\n", argv[arg]); usage(stderr, false); exit(1); } if (!(j.value()->section & sections)) { fprintf(stderr, "%s specified in incorrect location\n\n", argv[arg]); usage(stderr, false); exit(1); } //Check to see if there is enough arguments to the switch if (argc-arg < j.value()->argn.size()+1) { fprintf(stderr, "Not enough arguments parsed to %s\n\n", argv[arg]); usage(stderr, false); exit(1); } if (!(*(j.value()))(argv+arg+1, *this, page)) { fprintf(stderr, "Invalid argument(s) parsed to %s\n\n", argv[arg]); usage(stderr, false); exit(1); } #ifndef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ if (j.value()->qthack) fprintf(stderr, "The switch %s, is not support using unpatched qt, and will be ignored.", argv[arg]); #endif //Skip already handled switch arguments arg += j.value()->argn.size(); } else { int c=arg;//Remember the current argument we are parsing for (int j=1; argv[c][j] != '\0'; ++j) { QHash::iterator k = shortToHandler.find(argv[c][j]); //If the short argument is invalid print usage information and exit if (k == shortToHandler.end()) { fprintf(stderr, "Unknown switch -%c\n\n", argv[c][j]); usage(stderr, false); exit(1); } if (!(k.value()->section & sections)) { fprintf(stderr, "-%c specified in incorrect location\n\n", argv[c][j]); usage(stderr, false); exit(1); } //Check to see if there is enough arguments to the switch if (argc-arg < k.value()->argn.size()+1) { fprintf(stderr, "Not enough arguments parsed to -%c\n\n", argv[c][j]); usage(stderr, false); exit(1); } if (!(*(k.value()))(argv+arg+1, *this, page)) { fprintf(stderr, "Invalid argument(s) parsed to -%c\n\n", argv[c][j]); usage(stderr, false); exit(1); } #ifndef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__ if (k.value()->qthack) fprintf(stderr, "The switch -%c, is not support using unpatched qt, and will be ignored.", argv[c][j]); #endif //Skip already handled switch arguments arg += k.value()->argn.size(); } } } wkhtmltopdf-0.12.5/src/shared/commandlineparserbase.hh000066400000000000000000000056571343154624600231030ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __COMMANDLINEPARSERBASE_HH__ #define __COMMANDLINEPARSERBASE_HH__ #include #include class Outputter; class CommandLineParserBase; class ArgHandler { public: QString longName; QString desc; char shortSwitch; QVector argn; bool display; bool extended; bool qthack; virtual QString getDesc() const; virtual ~ArgHandler(); int section; virtual bool operator() (const char ** args, CommandLineParserBase & parser, char * page) = 0; }; class CommandLineParserBase { public: int currentMode; QString currentSection; bool currentExtended; bool currentHack; QList sections; QHash longToHandler; QHash shortToHandler; QHash > sectionArgumentHandles; QHash sectionDesc; //basearguments.cc void section(QString s, QString desc=""); void mode(int m); void qthack(bool); void extended(bool); void addarg(QString, char, QString, ArgHandler * h, bool display=true); void addDocArgs(); void addWebArgs(wkhtmltopdf::settings::Web & s); void addGlobalLoadArgs(wkhtmltopdf::settings::LoadGlobal & s); void addPageLoadArgs(wkhtmltopdf::settings::LoadPage & s); //commondocparts.cc void outputName(Outputter * o) const; void outputLicense(Outputter * o) const; void outputAuthors(Outputter * o) const; void outputStaticProblems(Outputter * o) const; void outputProxyDoc(Outputter * o) const; //commandlineparserbase.cc void outputSwitches(Outputter * o, bool extended, bool doc) const; virtual char * mapAddress(char * d, char *) const {return d;} virtual void license(FILE * fd) const; virtual void version(FILE * fd) const; void parseArg(int sections, const int argc, const char ** argv, bool & defaultMode, int & arg, char * page); virtual QString appName() const = 0; const char *appVersion() const; virtual void usage(FILE * fd, bool extended) const = 0; virtual void manpage(FILE * fd) const = 0; virtual void readme(FILE * fd, bool html) const = 0; }; #endif //__COMMANDLINEPARSERBASE_HH__ wkhtmltopdf-0.12.5/src/shared/commonarguments.cc000066400000000000000000000244761343154624600217510ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "arghandler.inl" #include "commandlineparserbase.hh" #include using namespace wkhtmltopdf::settings; struct LoadErrorHandlingTM: public SomeSetterTM { static LoadPage::LoadErrorHandling strToT(const char * val, bool &ok) { return strToLoadErrorHandling(val, &ok); } static QString TToStr(const LoadPage::LoadErrorHandling & o, bool & ok) { ok=true; return loadErrorHandlingToStr(o); } }; typedef SomeSetter LoadErrorHandlingSetting; struct ProxyTM: public SomeSetterTM { static Proxy strToT(const char * val, bool &ok) { return strToProxy(val, &ok); } }; /*! Argument handler setting a proxy variable */ typedef SomeSetter ProxySetter; //All these function would have been lambda function, had C++ supported them, now we are forced to write them here /*! Lambda: Call the usage method */ template struct HelpFunc { bool operator()(const char **, CommandLineParserBase & p, char *) { p.usage(stdout,v); exit(0); } }; /*! Lambda: Call the man method */ struct ManPageFunc { bool operator()(const char **, CommandLineParserBase & p, char *) { p.manpage(stdout); exit(0); } }; /*! Lambda: Call the man method */ template struct ReadmeFunc { bool operator()(const char **, CommandLineParserBase & p, char *) { p.readme(stdout, T); exit(0); } }; /*! Lambda: Call the version method */ struct VersionFunc { bool operator()(const char **, CommandLineParserBase & p, char *) { p.version(stdout); exit(0); } }; /*! Lambda: show the license */ struct LicenseFunc { bool operator()(const char **, CommandLineParserBase & p, char *) { p.license(stdout); exit(0); } }; /*! The next arguments we add will belong to this section /param s The name of the section /param desc A description of the section */ void CommandLineParserBase::section(QString s, QString desc) { currentSection = s; sectionDesc[s] = desc; sections.push_back(s); } /*! Indicate whether the next arguments we add require a patched qt to work /param h Do we require a patch */ void CommandLineParserBase::qthack(bool h) { currentHack = h; } void CommandLineParserBase::mode(int m) { currentMode = m; } /*! Indicate whether the next arguments we add are "extended" and should not be shown in a simple --help \param e Are the arguments extended */ void CommandLineParserBase::extended(bool e) { currentExtended = e; } /*! Add an argument to the list of arguments \param l The long "--" name of the argument \param s The short '-' name of the argument or 0 if unspecified \param d Description of the argument \param h The handler for the argument \param display Is the argument hidden */ void CommandLineParserBase::addarg(QString l, char s, QString d, ArgHandler * h, bool display) { h->desc = d; h->longName = l; h->shortSwitch = s; h->display = display; h->qthack = currentHack; h->section = currentMode; h->extended = currentExtended; longToHandler[l] = h; if (s) shortToHandler[s] = h; sectionArgumentHandles[currentSection].push_back(h); } void CommandLineParserBase::addDocArgs() { extended(false); qthack(false); addarg("help", 'h', "Display help", new Caller >()); addarg("version", 'V' ,"Output version information and exit", new Caller()); addarg("license", 0 ,"Output license information and exit", new Caller()); addarg("extended-help", 'H',"Display more extensive help, detailing less common command switches", new Caller >()); extended(true); qthack(false); addarg("manpage", 0, "Output program man page", new Caller()); addarg("htmldoc", 0, "Output program html help", new Caller >()); addarg("readme", 0, "Output program readme", new Caller >()); } void CommandLineParserBase::addGlobalLoadArgs(LoadGlobal & s) { extended(true); qthack(false); addarg("cookie-jar", 0, "Read and write cookies from and to the supplied cookie jar file", new QStrSetter(s.cookieJar, "path") ); } void CommandLineParserBase::addWebArgs(Web & s) { extended(true); qthack(false); addarg("enable-plugins",0,"Enable installed plugins (plugins will likely not work)", new ConstSetter(s.enablePlugins,true)); addarg("disable-plugins",0,"Disable installed plugins", new ConstSetter(s.enablePlugins,false)); addarg("minimum-font-size",0,"Minimum font size", new IntSetter(s.minimumFontSize,"int")); addarg("user-style-sheet",0,"Specify a user style sheet, to load with every page", new QStrSetter(s.userStyleSheet,"url")); addarg("no-images",0,"Do not load or print images", new ConstSetter(s.loadImages, false)); addarg("images",0,"Do load or print images", new ConstSetter(s.loadImages, true)); addarg("disable-javascript",'n',"Do not allow web pages to run javascript", new ConstSetter(s.enableJavascript,false)); addarg("enable-javascript",0,"Do allow web pages to run javascript", new ConstSetter(s.enableJavascript,true)); extended(true); qthack(true); qthack(false); addarg("encoding", 0, "Set the default text encoding, for input", new QStrSetter(s.defaultEncoding,"encoding")); } void CommandLineParserBase::addPageLoadArgs(LoadPage & s) { extended(true); qthack(false); addarg("proxy",'p',"Use a proxy", new ProxySetter(s.proxy, "proxy")); addarg("proxy-hostname-lookup", 0, "Use the proxy for resolving hostnames", new ConstSetter(s.proxyHostNameLookup, true)); addarg("bypass-proxy-for", 0, "Bypass proxy for host (repeatable)", new StringListSetter(s.bypassProxyForHosts, "value")); addarg("username",0,"HTTP Authentication username", new QStrSetter(s.username, "username")); addarg("password",0,"HTTP Authentication password", new QStrSetter(s.password, "password")); addarg("ssl-key-path",0,"Path to ssl client cert private key in OpenSSL PEM format", new QStrSetter(s.clientSslKeyPath, "path")); addarg("ssl-key-password",0,"Password to ssl client cert private key", new QStrSetter(s.clientSslKeyPassword, "password")); addarg("ssl-crt-path",0,"Path to the ssl client cert public key in OpenSSL PEM format, optionally followed by intermediate ca and trusted certs", new QStrSetter(s.clientSslCrtPath, "path")); addarg("load-error-handling", 0, "Specify how to handle pages that fail to load: abort, ignore or skip", new LoadErrorHandlingSetting(s.loadErrorHandling, "handler")); addarg("load-media-error-handling", 0, "Specify how to handle media files that fail to load: abort, ignore or skip", new LoadErrorHandlingSetting(s.mediaLoadErrorHandling, "handler")); addarg("custom-header",0,"Set an additional HTTP header (repeatable)", new MapSetter<>(s.customHeaders, "name", "value")); addarg("custom-header-propagation",0,"Add HTTP headers specified by --custom-header for each resource request.", new ConstSetter(s.repeatCustomHeaders, true)); addarg("no-custom-header-propagation",0,"Do not add HTTP headers specified by --custom-header for each resource request.", new ConstSetter(s.repeatCustomHeaders, true)); addarg("javascript-delay",0,"Wait some milliseconds for javascript finish", new IntSetter(s.jsdelay,"msec")); addarg("window-status",0,"Wait until window.status is equal to this string before rendering page", new QStrSetter(s.windowStatus, "windowStatus")); addarg("zoom",0,"Use this zoom factor", new FloatSetter(s.zoomFactor,"float",1.0)); addarg("cookie",0,"Set an additional cookie (repeatable), value should be url encoded.", new MapSetter<>(s.cookies, "name", "value")); addarg("post", 0, "Add an additional post field (repeatable)", new MapSetter >(s.post, "name", "value")); addarg("post-file", 0, "Post an additional file (repeatable)", new MapSetter >(s.post, "name", "path")); addarg("disable-local-file-access", 0, "Do not allowed conversion of a local file to read in other local files, unless explicitly allowed with --allow", new ConstSetter(s.blockLocalFileAccess, true)); addarg("enable-local-file-access", 0, "Allowed conversion of a local file to read in other local files.", new ConstSetter(s.blockLocalFileAccess, false)); addarg("allow", 0, "Allow the file or files from the specified folder to be loaded (repeatable)", new StringListSetter(s.allowed,"path")); addarg("cache-dir", 0, "Web cache directory", new QStrSetter(s.cacheDir,"path")); addarg("debug-javascript", 0,"Show javascript debugging output", new ConstSetter(s.debugJavascript, true)); addarg("no-debug-javascript", 0,"Do not show javascript debugging output", new ConstSetter(s.debugJavascript, false)); addarg("stop-slow-scripts", 0, "Stop slow running javascripts", new ConstSetter(s.stopSlowScripts, true)); addarg("no-stop-slow-scripts", 0, "Do not Stop slow running javascripts", new ConstSetter(s.stopSlowScripts, false)); addarg("run-script", 0, "Run this additional javascript after the page is done loading (repeatable)", new StringListSetter(s.runScript, "js")); addarg("checkbox-svg", 0, "Use this SVG file when rendering unchecked checkboxes", new QStrSetter(s.checkboxSvg, "path", "")); addarg("checkbox-checked-svg", 0, "Use this SVG file when rendering checked checkboxes", new QStrSetter(s.checkboxCheckedSvg, "path" ,"")); addarg("radiobutton-svg", 0, "Use this SVG file when rendering unchecked radiobuttons", new QStrSetter(s.radiobuttonSvg, "path", "")); addarg("radiobutton-checked-svg", 0, "Use this SVG file when rendering checked radiobuttons", new QStrSetter(s.radiobuttonCheckedSvg, "path", "")); } wkhtmltopdf-0.12.5/src/shared/commondocparts.cc000066400000000000000000000070711343154624600215530ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "commandlineparserbase.hh" #include "outputter.hh" #include /*! Output the name and version of the program, and also whether we are using a patched qt \param o The outputter to output to */ void CommandLineParserBase::outputName(Outputter * o) const { o->beginSection("Name"); o->paragraph(appName()+" "+appVersion()); o->endSection(); } /*! Output copyright stuff \param o The outputter to output to */ void CommandLineParserBase::outputLicense(Outputter * o) const { o->beginSection("License"); o->paragraph("Copyright (c) 2010-2014 wkhtmltopdf authors"); QFile file(":/LICENSE"); file.open(QIODevice::ReadOnly | QIODevice::Text); QTextStream stream(&file); o->verbatim(stream.readAll()); o->endSection(); } /*! Output list of authors \param o The outputter to output to */ void CommandLineParserBase::outputAuthors(Outputter * o) const { o->beginSection("Authors"); QFile file(":/AUTHORS"); file.open(QIODevice::ReadOnly | QIODevice::Text); QTextStream stream(&file); o->verbatim(stream.readAll()); o->endSection(); } /*! Output information on the problems with the static version \param o The outputter to output to */ void CommandLineParserBase::outputStaticProblems(Outputter * o) const { o->beginSection("Static version"); o->beginParagraph(); o->text("On the wkhtmltopdf website you can download a static version of wkhtmltopdf "); o->link("http://wkhtmltopdf.org/downloads.html"); o->text(". This static binary will work on most systems and comes with a build in patched QT."); o->endParagraph(); o->beginParagraph(); o->text("Unfortunately the static binary is not particularly static, on Linux it depends " "on both glibc and openssl, furthermore you will need to have an xserver installed " "but not necessary running. You will need to have different fonts install including " "xfonts-scalable (Type1), and msttcorefonts."); o->endParagraph(); o->endSection(); } /*! Output documentation about the proxy settings \param o The outputter to output to */ void CommandLineParserBase::outputProxyDoc(Outputter * o) const { o->beginSection("Specifying A Proxy"); o->paragraph( "By default proxy information will be read from the environment" " variables: proxy, all_proxy and http_proxy, proxy options can" " also by specified with the -p switch"); o->verbatim( " := \"http://\" | \"socks5://\"\n" " := (\":\" )? \"@\"\n" " := \"None\" | ? ? (\":\" )?\n"); o->paragraph("Here are some examples (In case you are unfamiliar with the BNF):"); o->verbatim("http://user:password@myproxyserver:8080\n" "socks5://myproxyserver\n" "None\n"); o->endSection(); } wkhtmltopdf-0.12.5/src/shared/htmloutputter.cc000066400000000000000000000073131343154624600214620ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "outputter.hh" #include #if QT_VERSION >= 0x050000 #define S(x) x.toHtmlEscaped().toUtf8().constData() #else #define S(x) Qt::escape(x).toUtf8().constData() #endif class HtmlOutputter: public Outputter { private: FILE * fd; bool ordered; public: HtmlOutputter(FILE * _): fd(_) { fprintf(fd, "\n" "\n" "\n" " \n" " wkhtmltopdf - Manual\n" " \n" ""); } ~HtmlOutputter() { fprintf(fd,"\n"); } void beginSection(const QString & name) { fprintf(fd, "

    %s

    \n", S(name), S(name)); } void endSection() { } void beginParagraph() { fprintf(fd,"

    "); } void endParagraph() { fprintf(fd,"

    \n"); } void text(const QString & t) { fprintf(fd, "%s", S(t)); } void sectionLink(const QString & s) { fprintf(fd, "%s", S(s), S(s)); } void bold(const QString & t) { fprintf(fd, "%s", S(t)); } void italic(const QString & t) { fprintf(fd, "%s", S(t)); } void link(const QString & t) { fprintf(fd, "%s", S(t),S(t)); } void verbatim(const QString & t) { fprintf(fd, "
    %s
    ", S(t)); } void beginList(bool o) { ordered = o; fprintf(fd, ordered?"
      ":"
        "); } void endList() { fprintf(fd, ordered?"
    ":""); } void listItem(const QString & s) { fprintf(fd, "
  • %s
  • \n", S(s)); } void beginSwitch() { fprintf(fd, "\n"); } void cswitch(const ArgHandler * h) { fprintf(fd, "\n",S(h->getDesc())); } void endSwitch() { fprintf(fd, "
    "); if (h->shortSwitch) fprintf(fd, "-%c,",h->shortSwitch); fprintf(fd, "--%s%s",S(h->longName), (h->qthack?"*":"")); foreach (const QString & arg, h->argn) fprintf(fd, "<%s> ",S(arg)); fprintf(fd, "%s
    \n"); fprintf(fd, "

    Items marked * are only available using patched QT.

    "); } }; /*! Create a Html outputter \param fd A file description to output to */ Outputter * Outputter::html(FILE * fd) { return new HtmlOutputter(fd); } wkhtmltopdf-0.12.5/src/shared/manoutputter.cc000066400000000000000000000056371343154624600213000ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "outputter.hh" #include #define S(x) ((x).toUtf8().constData()) class ManOutputter: public Outputter { private: FILE * fd; int order; public: ManOutputter(FILE * _): fd(_) { fprintf(fd,".TH WKHTMLTOPDF 1 \"2009 February 23\"\n\n"); } void beginSection(const QString & name) { fprintf(fd, ".SH %s\n", S(name)); } void endSection() { fprintf(fd, "\n"); } void beginParagraph() { } void endParagraph() { fprintf(fd, "\n\n"); } void text(const QString & t) { QString str = QString(t).replace("-", "\\-"); fprintf(fd, "%s", S(str)); } void sectionLink(const QString & t) { text(t); } void bold(const QString & t) { fprintf(fd, "\\fB%s\\fP", S(t)); } void italic(const QString & t) { fprintf(fd, "\\fB%s\\fP", S(t)); } void link(const QString & t) { fprintf(fd, "<%s>", S(t)); } void verbatim(const QString & t) { QString str = QString(t).replace("-", "\\-"); QStringList l = str.split('\n'); while ( l.back() == "") l.pop_back(); foreach (const QString & line, l) fprintf(fd, " %s\n", S(line)); fprintf(fd, "\n"); } void beginSwitch() { fprintf(fd, ".PD 0\n"); } void beginList(bool ordered) { order=(ordered?1:-1); } void endList() { fprintf(fd, "\n"); } void listItem(const QString & s) { if (order < 0) fprintf(fd, " * "); else fprintf(fd, "%3d ", order++); fprintf(fd,"%s\n",S(s)); } void cswitch(const ArgHandler * h) { fprintf(fd, ".TP\n"); fprintf(fd, "\\fB"); if (h->shortSwitch != 0) fprintf(fd, "\\-%c, ", h->shortSwitch); else fprintf(fd, " "); fprintf(fd,"\\-\\-%s\\fR", S(h->longName)); for (QVector::const_iterator i = h->argn.constBegin(); i != h->argn.constEnd(); ++i) fprintf(fd," \\fI<%s>\\fR", S(*i)); fprintf(fd, "\n%s\n", S(QString(h->desc).replace("-", "\\-"))); } void endSwitch() { fprintf(fd, ".PD\n"); fprintf(fd, "\n"); } }; /*! Create a man page outputter \param fd A file description to output to */ Outputter * Outputter::man(FILE * fd) { return new ManOutputter(fd); } wkhtmltopdf-0.12.5/src/shared/outputter.cc000066400000000000000000000052401343154624600205720ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "outputter.hh" /*! \class Outputter \brief Interface for classes used to output documentation */ /*! \fn Outputter::beginSection(const QString & name) Add a new section to the output \param name The name of the section */ /*! \fn Outputter::endSection() End the current section */ /*! \fn Outputter::beginParagraph() Begin a text paragraph */ /*! \fn Outputter::text(const QString & t) Add some text to the current paragraph \param t The text to add */ /*! \fn Outputter::bold(const QString & t) = 0; Add some bold text to the current paragraph \param t The text to add */ /*! \fn Outputter::italic(const QString & t) Add some italic text tho the current paragraph \param t The text to add */ /*! \fn Outputter::link(const QString & l) Add a hyperlink to somewhere \param l The url to link to */ /*! \fn Outputter::endParagraph() End the current paragraph */ /*! \fn Outputter::verbatim(const QString & t) Add a pice of code or verbatime text \param t The text to add */ /*! \fn Outputter::beginList(bool ordered=false) Begin a ordered or unordered listing \param ordered Should the list be ordered */ /*! \fn Outputter::endList() End the current listing */ /*! \fn Outputter::listItem(QString & t) Add an item to the current listing \param t The text to add */ /*! \fn Outputter::beginSwitch() Begin a section with command line switches */ /*! \fn Outputter::cswitch(const ArgHandler * h, bool doc) Output a switch description \param h The switch to add \param doc Are we outputting to documentation */ /*! \fn Outputter::endSwitch() End a switch section */ /*! Output a paragraph of simple text */ void Outputter::paragraph(const QString & t) { beginParagraph(); text(t); endParagraph(); } wkhtmltopdf-0.12.5/src/shared/outputter.hh000066400000000000000000000037021343154624600206050ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __OUTPUTTER_HH__ #define __OUTPUTTER_HH__ #include "commandlineparserbase.hh" #include #include #include class Outputter { public: virtual ~Outputter() {} virtual void beginSection(const QString & name) = 0; virtual void endSection() = 0; virtual void beginParagraph() = 0; virtual void text(const QString & t) = 0; virtual void bold(const QString & t) = 0; virtual void italic(const QString & t) = 0; virtual void link(const QString & l) = 0; virtual void sectionLink(const QString & s) = 0; virtual void endParagraph() = 0; virtual void verbatim(const QString & t) = 0; virtual void beginList(bool ordered=false) = 0; virtual void endList() = 0; virtual void listItem(const QString & t) = 0; virtual void beginSwitch() = 0; virtual void cswitch(const ArgHandler * h) = 0; virtual void endSwitch() = 0; void paragraph(const QString & t); static Outputter * text(FILE * fd, bool doc=false, bool extended=false); static Outputter * man(FILE * fd); static Outputter * html(FILE * fd); }; #endif //__OUTPUTTER_HH__ wkhtmltopdf-0.12.5/src/shared/progressfeedback.cc000066400000000000000000000065101343154624600220310ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "progressfeedback.hh" #include namespace wkhtmltopdf { /*! \file progressfeedback.hh \brief Define the ProgressFeedback class */ /*! \class ProgressFeedback \brief Produce progress feedback on the terminal */ #define S(t) ((t).toLocal8Bit().constData()) /*! \brief Write out a warning message \param message The warning message */ void ProgressFeedback::warning(const QString &message) { if (logLevel < settings::Warn) return; fprintf(stderr, "Warning: %s",S(message)); for (int l = 9 + message.size(); l < lw; ++l) fprintf(stderr, " "); fprintf(stderr, "\n"); lw = 0; fflush(stderr); } /*! \brief Write out an error message \param message The error message */ void ProgressFeedback::error(const QString &message) { if (logLevel < settings::Error) return; fprintf(stderr, "Error: %s",S(message)); for (int l = 7 + message.size(); l < lw; ++l) fprintf(stderr, " "); fprintf(stderr, "\n"); lw = 0; fflush(stderr); } /*! \brief Write out the name of the next phase */ void ProgressFeedback::phaseChanged() { if (logLevel < settings::Info) return; QString desc=converter.phaseDescription(); fprintf(stderr, "%s", S(desc)); int l = desc.size(); if (converter.currentPhase() < converter.phaseCount() -1) l += fprintf(stderr," (%d/%d)",converter.currentPhase()+1,converter.phaseCount()-1); for (; l < lw; ++l) fprintf(stderr, " "); fprintf(stderr, "\n"); lw = 0; fflush(stderr); } /*! \brief Update progress bar */ void ProgressFeedback::progressChanged(int progress) { if (logLevel < settings::Info) return; fprintf(stderr, "["); int w=60; progress *= w; progress /= 100; for (int i=0; i < w; ++i) { if (i < progress) fprintf(stderr, "="); else if (i == progress) fprintf(stderr, ">"); else fprintf(stderr, " "); } fprintf(stderr, "]"); fprintf(stderr, " %s", S(converter.progressString())); int l=1+w+2+converter.progressString().size(); for (int i=l; i < lw; ++i) fprintf(stderr, " "); lw = l; fprintf(stderr, "\r"); fflush(stderr); } ProgressFeedback::ProgressFeedback(settings::LogLevel l, Converter & _): logLevel(l), converter(_), lw(0) { connect(&converter, SIGNAL(warning(const QString &)), this, SLOT(warning(const QString &))); connect(&converter, SIGNAL(error(const QString &)), this, SLOT(error(const QString &))); connect(&converter, SIGNAL(phaseChanged()), this, SLOT(phaseChanged())); connect(&converter, SIGNAL(progressChanged(int)), this, SLOT(progressChanged(int))); } } wkhtmltopdf-0.12.5/src/shared/progressfeedback.hh000066400000000000000000000026231343154624600220440ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __PROGRESSFEEDBACK_HH__ #define __PROGRESSFEEDBACK_HH__ #include #include namespace wkhtmltopdf { class ProgressFeedback: public QObject { Q_OBJECT private: settings::LogLevel logLevel; Converter & converter; int lw; public slots: void warning(const QString &message); void error(const QString &message); void phaseChanged(); void progressChanged(int progress); public: ProgressFeedback(settings::LogLevel logLevel, Converter & _); }; } #endif //__PROGRESSFEEDBACK_HH__ wkhtmltopdf-0.12.5/src/shared/shared.pri000066400000000000000000000020411343154624600201660ustar00rootroot00000000000000# Copyright 2010, 2011 wkhtmltopdf authors # # This file is part of wkhtmltopdf. # # wkhtmltopdf is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # wkhtmltopdf is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with wkhtmltopdf. If not, see . HEADERS += ../shared/progressfeedback.hh SOURCES += ../shared/outputter.cc ../shared/manoutputter.cc ../shared/htmloutputter.cc \ ../shared/textoutputter.cc ../shared/arghandler.cc ../shared/commondocparts.cc \ ../shared/commandlineparserbase.cc ../shared/commonarguments.cc \ ../shared/progressfeedback.cc wkhtmltopdf-0.12.5/src/shared/textoutputter.cc000066400000000000000000000076221343154624600215050ustar00rootroot00000000000000// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #include "outputter.hh" #include #define S(t) (doc?(t).toUtf8().constData():(t).toLocal8Bit().constData()) class TextOutputter: public Outputter { public: FILE * fd; static const int lw = 80; int w; bool doc; bool extended; bool first; int order; TextOutputter(FILE * _, bool d, bool e): fd(_), doc(d), extended(e) {} void beginSection(const QString & name) { if (doc) { int x= 80 - name.size() - 4; if (x < 6) x = 60; for (int i=0; i < x/2; ++i) fprintf(fd, "="); fprintf(fd, "> %s <", S(name) ); for (int i=0; i < (x+1)/2; ++i) fprintf(fd, "="); fprintf(fd, "\n"); } else fprintf(fd, "%s:\n", S(name) ); } void endSection() { } void beginParagraph() { first=true; if (doc) { w=0; } else { w=2; fprintf(fd," "); } } void text(const QString & t) { first=true; QStringList list = t.split(" "); foreach (const QString & s, list) { if ( w + s.size() + (first?0:1) > lw) { fprintf(fd, "\n"); if (doc) { w=0; } else { w=2; fprintf(fd," "); } first=true; } if (first) first=false; else { fprintf(fd, " "); ++w; } w += s.size(); fprintf(fd, "%s", S(s)); } } void sectionLink(const QString & t) { text(t); } void bold(const QString & t) { text("*"+t+"*"); } void italic(const QString & t) { text("_"+t+"_"); } void link(const QString & t) { text("<"+t+">"); } void endParagraph() { fprintf(fd,"\n\n"); } void verbatim(const QString & t) { if (doc) fprintf(fd,"%s\n", S(t)); else { foreach (const QString & s, t.split("\n")) fprintf(fd," %s\n",S(s)); } } void beginList(bool ordered) { order=ordered?1:-1; } void endList() { fprintf(fd,"\n"); } void listItem(const QString & s) { if (order < 0) fprintf(fd, " * "); else fprintf(fd, "%3d ", order++); fprintf(fd,"%s\n",S(s)); } void beginSwitch() {} void cswitch(const ArgHandler * h) { w=0; if (!doc) {fprintf(fd," "); w=2;} if (h->shortSwitch != 0) fprintf(fd,"-%c, ",h->shortSwitch); else fprintf(fd," "); fprintf(fd,"--%s",S(h->longName)); w+=4 + 2 + h->longName.size(); if (doc && h->qthack) { fprintf(fd, " *"); w += 2; } foreach (const QString & arg, h->argn) { fprintf(fd," <%s>",S(arg)); w+=3+arg.size(); } while (w < 37) { fprintf(fd," "); ++w; } foreach (const QString & s, h->getDesc().split(" ")) { if (w+1+s.size() > lw) { printf("\n"); w=0; while (w < 37) { fprintf(fd," "); ++w; } } fprintf(fd, " %s", S(s)); w += s.size() + 1; } fprintf(fd,"\n"); } void endSwitch() { if (doc) fprintf(fd, "\nItems marked * are only available using patched QT.\n"); printf("\n"); } }; /*! Create a raw text outputter, used for outputting --help and readme \param fd A file description to output to \param doc Output in readme format \param extended Output extended options */ Outputter * Outputter::text(FILE * fd, bool doc, bool extended) { return new TextOutputter(fd, doc, extended); } wkhtmltopdf-0.12.5/wkhtmltopdf.pro000066400000000000000000000014421343154624600172400ustar00rootroot00000000000000# Copyright 2010, 2011 wkhtmltopdf authors # # This file is part of wkhtmltopdf. # # wkhtmltopdf is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # wkhtmltopdf is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with wkhtmltopdf. If not, see . TEMPLATE = subdirs CONFIG += ordered SUBDIRS = src/lib src/pdf src/image wkhtmltopdf-0.12.5/wkhtmltopdf.qrc000066400000000000000000000001701343154624600172220ustar00rootroot00000000000000 AUTHORS LICENSE