Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Backports:SLE-15-SP4:FactoryCandidates
diff-pdf
diff-pdf-0.5.obscpio
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File diff-pdf-0.5.obscpio of Package diff-pdf
07070100000000000081A4000003E800000064000000016039353E0000035A000000000000000000000000000000000000001B00000000diff-pdf-0.5/.appveyor.ymlimage: - Ubuntu - Visual Studio 2019 for: - matrix: except: - image: Ubuntu environment: MSYSTEM: MINGW32 PATH: C:\msys64\%MSYSTEM%\bin;C:\msys64\usr\bin;%PATH% CHERE_INVOKING: 1 install: - sh: sudo apt-get update - sh: sudo apt-get --yes install libpoppler-glib-dev poppler-utils libwxgtk3.0-dev - cmd: sh -lc "pacman --noconfirm -Syuu" - cmd: sh -lc "pacman --noconfirm -S zip mingw-w64-i686-{poppler,wxWidgets}" build_script: - sh: ./bootstrap && ./configure && make - cmd: sh -lc "./bootstrap && ./configure && make" after_build: - sh: make dist - sh: appveyor PushArtifact diff-pdf*.tar.gz - cmd: sh -lc "make windows-dist" - ps: Get-ChildItem .\diff-pdf*.zip | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } deploy: provider: Environment name: github on: APPVEYOR_REPO_TAG: true 07070100000001000081A4000003E800000064000000016039353E0000003E000000000000000000000000000000000000001500000000diff-pdf-0.5/AUTHORS Developers: ------------- Vaclav Slavik <vaclav@slavik.io> 07070100000002000081A4000003E800000064000000016039353E00004652000000000000000000000000000000000000001500000000diff-pdf-0.5/COPYING GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. <signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. 07070100000003000081A4000003E800000064000000016039353E00000061000000000000000000000000000000000000001B00000000diff-pdf-0.5/COPYING.icons The gtk-zoom-in.xpm and gtk-zoom-out.xpm icons are under LGPL and were taken from GTK+ 2.16.5. 07070100000004000081A4000003E800000064000000016039353E00000275000000000000000000000000000000000000001900000000diff-pdf-0.5/Makefile.am bin_PROGRAMS = diff-pdf diff_pdf_SOURCES = \ diff-pdf.cpp \ bmpviewer.cpp \ bmpviewer.h \ gutter.cpp \ gutter.h diff_pdf_CXXFLAGS = $(POPPLER_CFLAGS) $(WX_CXXFLAGS) diff_pdf_LDADD = $(POPPLER_LIBS) $(WX_LIBS) EXTRA_DIST = bootstrap gtk-zoom-in.xpm gtk-zoom-out.xpm README.md win32/fonts.conf win32/collect-dlls.sh windows-dist: diff-pdf-win-$(VERSION).zip diff-pdf-win-$(VERSION).zip: all rm -rf $@ windist $(srcdir)/win32/collect-dlls.sh windist diff-pdf.exe mkdir -p windist/fonts && cp -a $(srcdir)/win32/fonts.conf windist/fonts/ (cd windist && zip -9r ../$@ .) rm -rf windist .PHONY: windows-dist 07070100000005000081A4000003E800000064000000016039353E0000129D000000000000000000000000000000000000001700000000diff-pdf-0.5/README.md*Note: this repository is provided **as-is** and the code is not being actively developed. If you wish to improve it, that's greatly appreciated: please make the changes and submit a pull request, I'll gladly merge it or help you out with finishing it. However, please do not expect any kind of support, including implementation of feature requests or fixes. If you're not a developer and/or willing to get your hands dirty, this tool is probably not for you.* [![Build status](https://ci.appveyor.com/api/projects/status/m6d8n2kcyvk3cqi6?svg=true)](https://ci.appveyor.com/project/vslavik/diff-pdf) ## Usage diff-pdf is a tool for visually comparing two PDFs. It takes two PDF files as arguments. By default, its only output is its return code, which is 0 if there are no differences and 1 if the two PDFs differ. If given the `--output-diff` option, it produces a PDF file with visually highlighted differences: ``` $ diff-pdf --output-diff=diff.pdf a.pdf b.pdf ``` Another option is to compare the two files visually in a simple GUI, using the `--view` argument: ``` $ diff-pdf --view a.pdf b.pdf ``` This opens a window that lets you view the files' pages and zoom in on details. It is also possible to shift the two pages relatively to each other using Ctrl-arrows (Cmd-arrows on MacOS). This is useful for identifying translation-only differences. See the output of `$ diff-pdf --help` for complete list of options. ## Obtaining the binaries Precompiled version of the tool for Windows is available as part of [the latest release](https://github.com/vslavik/diff-pdf/releases/tag/v0.5) as a ZIP archive, which contains everything you need to run diff-pdf. It will work from any place you unpack it to. On Mac, if you use [Homebrew](https://brew.sh), you can use it to install diff-pdf with it: ``` $ brew install diff-pdf ``` On Mac, if you use [Macports](https://macports.org), you can install diff-pdf with: ``` $ port install diff-pdf ``` On Fedora and CentOS 8: ``` $ sudo dnf install diff-pdf ``` Precompiled version for openSUSE can be downloaded from the [openSUSE build service](http://software.opensuse.org). ## Compiling from sources The build system uses Automake and so a Unix or Unix-like environment (Cygwin or MSYS) is required. Compilation is done in the usual way: ``` $ ./bootstrap $ ./configure $ make $ make install ``` (Note that the first step, running the `./bootstrap` script, is only required when building sources checked from version control system, i.e. when `configure` and `Makefile.in` files are missing.) As for dependencies, diff-pdf requires the following libraries: - wxWidgets >= 3.0 - Cairo >= 1.4 - Poppler >= 0.10 #### CentOS: ``` $ sudo yum groupinstall "Development Tools" $ sudo yum install wxGTK wxGTK-devel poppler-glib poppler-glib-devel ``` #### Ubuntu: ``` $ sudo apt-get install make automake g++ $ sudo apt-get install libpoppler-glib-dev poppler-utils libwxgtk3.0-gtk3-dev ``` #### macOS: Install Command Line Tools for Xcode: ``` $ xcode-select --install ``` and install [Homebrew](https://brew.sh) or [MacPorts](https://www.macports.org) to manage dependencies, then: ``` $ brew install automake autoconf wxmac poppler cairo pkg-config ``` or ``` $ sudo port install automake autoconf wxWidgets-3.0 poppler cairo pkgconfig ``` Note that many more libraries are required on Windows, where none of the libraries Cairo and Poppler use are normally available. At the time of writing, transitive cover of the above dependencies included fontconfig, freetype, glib, libpng, pixman, gettext, libiconv, libjpeg and zlib. ### Compiling on Windows using MSYS + MinGW 1. First of all, you will need working MinGW installation with MSYS2 environment and C++ compiler. Install MSYS2 by following [their instructions](https://www.msys2.org). 1. Once installed, launch the MSYS2 MinGW shell. It will open a terminal window; type `cd /c/directory/with/diff-pdf` to go to the directory with diff-pdf sources. 1. You will need to install additional MSYS components that are not normally included with MSYS, using these commands: ``` $ pacman -Syu $ pacman -S automake autoconf pkg-config make zip $ pacman -S mingw-w64-i686-{gcc,poppler,wxWidgets} ``` 1. Build diff-pdf in the same way as in the instructions for Unix above: ``` $ ./bootstrap # only if building from git repository $ ./configure $ make ``` 1. To build a ZIP archive will all DLLs, run ``` $ make windows-dist ``` ## Installing On Unix, the usual `make install` is sufficient. On Windows, installation is not necessary, just copy the files somewhere. If you built it following the instructions above, all the necessary files will be in the created ZIP archive. 07070100000006000041ED000003E800000064000000026039353E00000000000000000000000000000000000000000000001300000000diff-pdf-0.5/admin07070100000007000081A4000003E800000064000000016039353E00009E71000000000000000000000000000000000000001C00000000diff-pdf-0.5/admin/wxwin.m4dnl --------------------------------------------------------------------------- dnl Author: wxWidgets development team, dnl Francesco Montorsi, dnl Bob McCown (Mac-testing) dnl Creation date: 24/11/2001 dnl --------------------------------------------------------------------------- dnl =========================================================================== dnl Table of Contents of this macro file: dnl ------------------------------------- dnl dnl SECTION A: wxWidgets main macros dnl - WX_CONFIG_OPTIONS dnl - WX_CONFIG_CHECK dnl - WXRC_CHECK dnl - WX_STANDARD_OPTIONS dnl - WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS dnl - WX_DETECT_STANDARD_OPTION_VALUES dnl dnl SECTION B: wxWidgets-related utilities dnl - WX_LIKE_LIBNAME dnl - WX_ARG_ENABLE_YESNOAUTO dnl - WX_ARG_WITH_YESNOAUTO dnl dnl SECTION C: messages to the user dnl - WX_STANDARD_OPTIONS_SUMMARY_MSG dnl - WX_STANDARD_OPTIONS_SUMMARY_MSG_BEGIN dnl - WX_STANDARD_OPTIONS_SUMMARY_MSG_END dnl - WX_BOOLOPT_SUMMARY dnl dnl The special "WX_DEBUG_CONFIGURE" variable can be set to 1 to enable extra dnl debug output on stdout from these macros. dnl =========================================================================== dnl --------------------------------------------------------------------------- dnl Macros for wxWidgets detection. Typically used in configure.in as: dnl dnl AC_ARG_ENABLE(...) dnl AC_ARG_WITH(...) dnl ... dnl WX_CONFIG_OPTIONS dnl ... dnl ... dnl WX_CONFIG_CHECK([2.6.0], [wxWin=1]) dnl if test "$wxWin" != 1; then dnl AC_MSG_ERROR([ dnl wxWidgets must be installed on your system dnl but wx-config script couldn't be found. dnl dnl Please check that wx-config is in path, the directory dnl where wxWidgets libraries are installed (returned by dnl 'wx-config --libs' command) is in LD_LIBRARY_PATH or dnl equivalent variable and wxWidgets version is 2.3.4 or above. dnl ]) dnl fi dnl CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS" dnl CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS_ONLY" dnl CFLAGS="$CFLAGS $WX_CFLAGS_ONLY" dnl dnl LIBS="$LIBS $WX_LIBS" dnl dnl If you want to support standard --enable-debug/unicode/shared options, you dnl may do the following: dnl dnl ... dnl AC_CANONICAL_SYSTEM dnl dnl # define configure options dnl WX_CONFIG_OPTIONS dnl WX_STANDARD_OPTIONS([debug,unicode,shared,toolkit,wxshared]) dnl dnl # basic configure checks dnl ... dnl dnl # we want to always have DEBUG==WX_DEBUG and UNICODE==WX_UNICODE dnl WX_DEBUG=$DEBUG dnl WX_UNICODE=$UNICODE dnl dnl WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS dnl WX_CONFIG_CHECK([2.8.0], [wxWin=1],,[html,core,net,base],[$WXCONFIG_FLAGS]) dnl WX_DETECT_STANDARD_OPTION_VALUES dnl dnl # write the output files dnl AC_CONFIG_FILES([Makefile ...]) dnl AC_OUTPUT dnl dnl # optional: just to show a message to the user dnl WX_STANDARD_OPTIONS_SUMMARY_MSG dnl dnl --------------------------------------------------------------------------- dnl --------------------------------------------------------------------------- dnl WX_CONFIG_OPTIONS dnl dnl adds support for --wx-prefix, --wx-exec-prefix, --with-wxdir and dnl --wx-config command line options dnl --------------------------------------------------------------------------- AC_DEFUN([WX_CONFIG_OPTIONS], [ AC_ARG_WITH(wxdir, [ --with-wxdir=PATH Use uninstalled version of wxWidgets in PATH], [ wx_config_name="$withval/wx-config" wx_config_args="--inplace"]) AC_ARG_WITH(wx-config, [ --with-wx-config=CONFIG wx-config script to use (optional)], wx_config_name="$withval" ) AC_ARG_WITH(wx-prefix, [ --with-wx-prefix=PREFIX Prefix where wxWidgets is installed (optional)], wx_config_prefix="$withval", wx_config_prefix="") AC_ARG_WITH(wx-exec-prefix, [ --with-wx-exec-prefix=PREFIX Exec prefix where wxWidgets is installed (optional)], wx_config_exec_prefix="$withval", wx_config_exec_prefix="") ]) dnl Helper macro for checking if wx version is at least $1.$2.$3, set's dnl wx_ver_ok=yes if it is: AC_DEFUN([_WX_PRIVATE_CHECK_VERSION], [ wx_ver_ok="" if test "x$WX_VERSION" != x ; then if test $wx_config_major_version -gt $1; then wx_ver_ok=yes else if test $wx_config_major_version -eq $1; then if test $wx_config_minor_version -gt $2; then wx_ver_ok=yes else if test $wx_config_minor_version -eq $2; then if test $wx_config_micro_version -ge $3; then wx_ver_ok=yes fi fi fi fi fi fi ]) dnl --------------------------------------------------------------------------- dnl WX_CONFIG_CHECK(VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND dnl [, WX-LIBS [, ADDITIONAL-WX-CONFIG-FLAGS]]]]) dnl dnl Test for wxWidgets, and define WX_C*FLAGS, WX_LIBS and WX_LIBS_STATIC dnl (the latter is for static linking against wxWidgets). Set WX_CONFIG_NAME dnl environment variable to override the default name of the wx-config script dnl to use. Set WX_CONFIG_PATH to specify the full path to wx-config - in this dnl case the macro won't even waste time on tests for its existence. dnl dnl Optional WX-LIBS argument contains comma- or space-separated list of dnl wxWidgets libraries to link against. If it is not specified then WX_LIBS dnl and WX_LIBS_STATIC will contain flags to link with all of the core dnl wxWidgets libraries. dnl dnl Optional ADDITIONAL-WX-CONFIG-FLAGS argument is appended to wx-config dnl invocation command in present. It can be used to fine-tune lookup of dnl best wxWidgets build available. dnl dnl Example use: dnl WX_CONFIG_CHECK([2.6.0], [wxWin=1], [wxWin=0], [html,core,net] dnl [--unicode --debug]) dnl --------------------------------------------------------------------------- dnl dnl Get the cflags and libraries from the wx-config script dnl AC_DEFUN([WX_CONFIG_CHECK], [ dnl do we have wx-config name: it can be wx-config or wxd-config or ... if test x${WX_CONFIG_NAME+set} != xset ; then WX_CONFIG_NAME=wx-config fi if test "x$wx_config_name" != x ; then WX_CONFIG_NAME="$wx_config_name" fi dnl deal with optional prefixes if test x$wx_config_exec_prefix != x ; then wx_config_args="$wx_config_args --exec-prefix=$wx_config_exec_prefix" WX_LOOKUP_PATH="$wx_config_exec_prefix/bin" fi if test x$wx_config_prefix != x ; then wx_config_args="$wx_config_args --prefix=$wx_config_prefix" WX_LOOKUP_PATH="$WX_LOOKUP_PATH:$wx_config_prefix/bin" fi if test "$cross_compiling" = "yes"; then wx_config_args="$wx_config_args --host=$host_alias" fi dnl don't search the PATH if WX_CONFIG_NAME is absolute filename if test -x "$WX_CONFIG_NAME" ; then AC_MSG_CHECKING(for wx-config) WX_CONFIG_PATH="$WX_CONFIG_NAME" AC_MSG_RESULT($WX_CONFIG_PATH) else AC_PATH_PROG(WX_CONFIG_PATH, $WX_CONFIG_NAME, no, "$WX_LOOKUP_PATH:$PATH") fi if test "$WX_CONFIG_PATH" != "no" ; then WX_VERSION="" min_wx_version=ifelse([$1], ,2.2.1,$1) if test -z "$5" ; then AC_MSG_CHECKING([for wxWidgets version >= $min_wx_version]) else AC_MSG_CHECKING([for wxWidgets version >= $min_wx_version ($5)]) fi dnl don't add the libraries ($4) to this variable as this would result in dnl an error when it's used with --version below WX_CONFIG_WITH_ARGS="$WX_CONFIG_PATH $wx_config_args $5" WX_VERSION=`$WX_CONFIG_WITH_ARGS --version 2>/dev/null` wx_config_major_version=`echo $WX_VERSION | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` wx_config_minor_version=`echo $WX_VERSION | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` wx_config_micro_version=`echo $WX_VERSION | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` wx_requested_major_version=`echo $min_wx_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` wx_requested_minor_version=`echo $min_wx_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` wx_requested_micro_version=`echo $min_wx_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` _WX_PRIVATE_CHECK_VERSION([$wx_requested_major_version], [$wx_requested_minor_version], [$wx_requested_micro_version]) if test -n "$wx_ver_ok"; then AC_MSG_RESULT(yes (version $WX_VERSION)) WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs $4` dnl is this even still appropriate? --static is a real option now dnl and WX_CONFIG_WITH_ARGS is likely to contain it if that is dnl what the user actually wants, making this redundant at best. dnl For now keep it in case anyone actually used it in the past. AC_MSG_CHECKING([for wxWidgets static library]) WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs $4 2>/dev/null` if test "x$WX_LIBS_STATIC" = "x"; then AC_MSG_RESULT(no) else AC_MSG_RESULT(yes) fi dnl starting with version 2.2.6 wx-config has --cppflags argument wx_has_cppflags="" if test $wx_config_major_version -gt 2; then wx_has_cppflags=yes else if test $wx_config_major_version -eq 2; then if test $wx_config_minor_version -gt 2; then wx_has_cppflags=yes else if test $wx_config_minor_version -eq 2; then if test $wx_config_micro_version -ge 6; then wx_has_cppflags=yes fi fi fi fi fi dnl starting with version 2.7.0 wx-config has --rescomp option wx_has_rescomp="" if test $wx_config_major_version -gt 2; then wx_has_rescomp=yes else if test $wx_config_major_version -eq 2; then if test $wx_config_minor_version -ge 7; then wx_has_rescomp=yes fi fi fi if test "x$wx_has_rescomp" = x ; then dnl cannot give any useful info for resource compiler WX_RESCOMP= else WX_RESCOMP=`$WX_CONFIG_WITH_ARGS --rescomp` fi if test "x$wx_has_cppflags" = x ; then dnl no choice but to define all flags like CFLAGS WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags $4` WX_CPPFLAGS=$WX_CFLAGS WX_CXXFLAGS=$WX_CFLAGS WX_CFLAGS_ONLY=$WX_CFLAGS WX_CXXFLAGS_ONLY=$WX_CFLAGS else dnl we have CPPFLAGS included in CFLAGS included in CXXFLAGS WX_CPPFLAGS=`$WX_CONFIG_WITH_ARGS --cppflags $4` WX_CXXFLAGS=`$WX_CONFIG_WITH_ARGS --cxxflags $4` WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags $4` WX_CFLAGS_ONLY=`echo $WX_CFLAGS | sed "s@^$WX_CPPFLAGS *@@"` WX_CXXFLAGS_ONLY=`echo $WX_CXXFLAGS | sed "s@^$WX_CFLAGS *@@"` fi ifelse([$2], , :, [$2]) else if test "x$WX_VERSION" = x; then dnl no wx-config at all AC_MSG_RESULT(no) else AC_MSG_RESULT(no (version $WX_VERSION is not new enough)) fi WX_CFLAGS="" WX_CPPFLAGS="" WX_CXXFLAGS="" WX_LIBS="" WX_LIBS_STATIC="" WX_RESCOMP="" if test ! -z "$5"; then wx_error_message=" The configuration you asked for $PACKAGE_NAME requires a wxWidgets build with the following settings: $5 but such build is not available. To see the wxWidgets builds available on this system, please use 'wx-config --list' command. To use the default build, returned by 'wx-config --selected-config', use the options with their 'auto' default values." fi wx_error_message=" The requested wxWidgets build couldn't be found. $wx_error_message If you still get this error, then check that 'wx-config' is in path, the directory where wxWidgets libraries are installed (returned by 'wx-config --libs' command) is in LD_LIBRARY_PATH or equivalent variable and wxWidgets version is $1 or above." ifelse([$3], , AC_MSG_ERROR([$wx_error_message]), [$3]) fi else WX_CFLAGS="" WX_CPPFLAGS="" WX_CXXFLAGS="" WX_LIBS="" WX_LIBS_STATIC="" WX_RESCOMP="" ifelse([$3], , :, [$3]) fi AC_SUBST(WX_CPPFLAGS) AC_SUBST(WX_CFLAGS) AC_SUBST(WX_CXXFLAGS) AC_SUBST(WX_CFLAGS_ONLY) AC_SUBST(WX_CXXFLAGS_ONLY) AC_SUBST(WX_LIBS) AC_SUBST(WX_LIBS_STATIC) AC_SUBST(WX_VERSION) AC_SUBST(WX_RESCOMP) dnl need to export also WX_VERSION_MINOR and WX_VERSION_MAJOR symbols dnl to support wxpresets bakefiles (we export also WX_VERSION_MICRO for completeness): WX_VERSION_MAJOR="$wx_config_major_version" WX_VERSION_MINOR="$wx_config_minor_version" WX_VERSION_MICRO="$wx_config_micro_version" AC_SUBST(WX_VERSION_MAJOR) AC_SUBST(WX_VERSION_MINOR) AC_SUBST(WX_VERSION_MICRO) ]) dnl --------------------------------------------------------------------------- dnl Get information on the wxrc program for making C++, Python and xrs dnl resource files. dnl dnl AC_ARG_ENABLE(...) dnl AC_ARG_WITH(...) dnl ... dnl WX_CONFIG_OPTIONS dnl ... dnl WX_CONFIG_CHECK(2.6.0, wxWin=1) dnl if test "$wxWin" != 1; then dnl AC_MSG_ERROR([ dnl wxWidgets must be installed on your system dnl but wx-config script couldn't be found. dnl dnl Please check that wx-config is in path, the directory dnl where wxWidgets libraries are installed (returned by dnl 'wx-config --libs' command) is in LD_LIBRARY_PATH or dnl equivalent variable and wxWidgets version is 2.6.0 or above. dnl ]) dnl fi dnl dnl WXRC_CHECK([HAVE_WXRC=1], [HAVE_WXRC=0]) dnl if test "x$HAVE_WXRC" != x1; then dnl AC_MSG_ERROR([ dnl The wxrc program was not installed or not found. dnl dnl Please check the wxWidgets installation. dnl ]) dnl fi dnl dnl CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS" dnl CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS_ONLY" dnl CFLAGS="$CFLAGS $WX_CFLAGS_ONLY" dnl dnl LDFLAGS="$LDFLAGS $WX_LIBS" dnl --------------------------------------------------------------------------- dnl --------------------------------------------------------------------------- dnl WXRC_CHECK([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) dnl dnl Test for wxWidgets' wxrc program for creating either C++, Python or XRS dnl resources. The variable WXRC will be set and substituted in the configure dnl script and Makefiles. dnl dnl Example use: dnl WXRC_CHECK([wxrc=1], [wxrc=0]) dnl --------------------------------------------------------------------------- dnl dnl wxrc program from the wx-config script dnl AC_DEFUN([WXRC_CHECK], [ AC_ARG_VAR([WXRC], [Path to wxWidget's wxrc resource compiler]) if test "x$WX_CONFIG_NAME" = x; then AC_MSG_ERROR([The wxrc tests must run after wxWidgets test.]) else AC_MSG_CHECKING([for wxrc]) if test "x$WXRC" = x ; then dnl wx-config --utility is a new addition to wxWidgets: _WX_PRIVATE_CHECK_VERSION(2,5,3) if test -n "$wx_ver_ok"; then WXRC=`$WX_CONFIG_WITH_ARGS --utility=wxrc` fi fi if test "x$WXRC" = x ; then AC_MSG_RESULT([not found]) ifelse([$2], , :, [$2]) else AC_MSG_RESULT([$WXRC]) ifelse([$1], , :, [$1]) fi AC_SUBST(WXRC) fi ]) dnl --------------------------------------------------------------------------- dnl WX_LIKE_LIBNAME([output-var] [prefix], [name]) dnl dnl Sets the "output-var" variable to the name of a library named with same dnl wxWidgets rule. dnl E.g. for output-var=='lib', name=='test', prefix='mine', sets dnl the $lib variable to: dnl 'mine_gtk2ud_test-2.8' dnl if WX_PORT=gtk2, WX_UNICODE=1, WX_DEBUG=1 and WX_RELEASE=28 dnl --------------------------------------------------------------------------- AC_DEFUN([WX_LIKE_LIBNAME], [ wx_temp="$2""_""$WX_PORT" dnl add the [u][d] string if test "$WX_UNICODE" = "1"; then wx_temp="$wx_temp""u" fi if test "$WX_DEBUG" = "1"; then wx_temp="$wx_temp""d" fi dnl complete the name of the lib wx_temp="$wx_temp""_""$3""-$WX_VERSION_MAJOR.$WX_VERSION_MINOR" dnl save it in the user's variable $1=$wx_temp ]) dnl --------------------------------------------------------------------------- dnl WX_ARG_ENABLE_YESNOAUTO/WX_ARG_WITH_YESNOAUTO dnl dnl Two little custom macros which define the ENABLE/WITH configure arguments. dnl Macro arguments: dnl $1 = the name of the --enable / --with feature dnl $2 = the name of the variable associated dnl $3 = the description of that feature dnl $4 = the default value for that feature dnl $5 = additional action to do in case option is given with "yes" value dnl --------------------------------------------------------------------------- AC_DEFUN([WX_ARG_ENABLE_YESNOAUTO], [AC_ARG_ENABLE($1, AC_HELP_STRING([--enable-$1], [$3 (default is $4)]), [], [enableval="$4"]) dnl Show a message to the user about this option AC_MSG_CHECKING([for the --enable-$1 option]) if test "$enableval" = "yes" ; then AC_MSG_RESULT([yes]) $2=1 $5 elif test "$enableval" = "no" ; then AC_MSG_RESULT([no]) $2=0 elif test "$enableval" = "auto" ; then AC_MSG_RESULT([will be automatically detected]) $2="auto" else AC_MSG_ERROR([ Unrecognized option value (allowed values: yes, no, auto) ]) fi ]) AC_DEFUN([WX_ARG_WITH_YESNOAUTO], [AC_ARG_WITH($1, AC_HELP_STRING([--with-$1], [$3 (default is $4)]), [], [withval="$4"]) dnl Show a message to the user about this option AC_MSG_CHECKING([for the --with-$1 option]) if test "$withval" = "yes" ; then AC_MSG_RESULT([yes]) $2=1 $5 dnl NB: by default we don't allow --with-$1=no option dnl since it does not make much sense ! elif test "$6" = "1" -a "$withval" = "no" ; then AC_MSG_RESULT([no]) $2=0 elif test "$withval" = "auto" ; then AC_MSG_RESULT([will be automatically detected]) $2="auto" else AC_MSG_ERROR([ Unrecognized option value (allowed values: yes, auto) ]) fi ]) dnl --------------------------------------------------------------------------- dnl WX_STANDARD_OPTIONS([options-to-add]) dnl dnl Adds to the configure script one or more of the following options: dnl --enable-[debug|unicode|shared|wxshared|wxdebug] dnl --with-[gtk|msw|motif|x11|mac|dfb] dnl --with-wxversion dnl Then checks for their presence and eventually set the DEBUG, UNICODE, SHARED, dnl PORT, WX_SHARED, WX_DEBUG, variables to one of the "yes", "no", "auto" values. dnl dnl Note that e.g. UNICODE != WX_UNICODE; the first is the value of the dnl --enable-unicode option (in boolean format) while the second indicates dnl if wxWidgets was built in Unicode mode (and still is in boolean format). dnl --------------------------------------------------------------------------- AC_DEFUN([WX_STANDARD_OPTIONS], [ dnl the following lines will expand to WX_ARG_ENABLE_YESNOAUTO calls if and only if dnl the $1 argument contains respectively the debug,unicode or shared options. dnl be careful here not to set debug flag if only "wxdebug" was specified ifelse(regexp([$1], [\bdebug]), [-1],, [WX_ARG_ENABLE_YESNOAUTO([debug], [DEBUG], [Build in debug mode], [auto])]) ifelse(index([$1], [unicode]), [-1],, [WX_ARG_ENABLE_YESNOAUTO([unicode], [UNICODE], [Build in Unicode mode], [auto])]) ifelse(regexp([$1], [\bshared]), [-1],, [WX_ARG_ENABLE_YESNOAUTO([shared], [SHARED], [Build as shared library], [auto])]) dnl WX_ARG_WITH_YESNOAUTO cannot be used for --with-toolkit since it's an option dnl which must be able to accept the auto|gtk1|gtk2|msw|... values ifelse(index([$1], [toolkit]), [-1],, [ AC_ARG_WITH([toolkit], AC_HELP_STRING([--with-toolkit], [Build against a specific wxWidgets toolkit (default is auto)]), [], [withval="auto"]) dnl Show a message to the user about this option AC_MSG_CHECKING([for the --with-toolkit option]) if test "$withval" = "auto" ; then AC_MSG_RESULT([will be automatically detected]) TOOLKIT="auto" else TOOLKIT="$withval" dnl PORT must be one of the allowed values if test "$TOOLKIT" != "gtk1" -a "$TOOLKIT" != "gtk2" -a \ "$TOOLKIT" != "msw" -a "$TOOLKIT" != "motif" -a \ "$TOOLKIT" != "osx_carbon" -a "$TOOLKIT" != "osx_cocoa" -a \ "$TOOLKIT" != "dfb" -a "$TOOLKIT" != "x11"; then AC_MSG_ERROR([ Unrecognized option value (allowed values: auto, gtk1, gtk2, msw, motif, osx_carbon, osx_cocoa, dfb, x11) ]) fi AC_MSG_RESULT([$TOOLKIT]) fi ]) dnl ****** IMPORTANT ******* dnl Unlike for the UNICODE setting, you can build your program in dnl shared mode against a static build of wxWidgets. Thus we have the dnl following option which allows these mixtures. E.g. dnl dnl ./configure --disable-shared --with-wxshared dnl dnl will build your library in static mode against the first available dnl shared build of wxWidgets. dnl dnl Note that's not possible to do the viceversa: dnl dnl ./configure --enable-shared --without-wxshared dnl dnl Doing so you would try to build your library in shared mode against a static dnl build of wxWidgets. This is not possible (you would mix PIC and non PIC code) ! dnl A check for this combination of options is in WX_DETECT_STANDARD_OPTION_VALUES dnl (where we know what 'auto' should be expanded to). dnl dnl If you try to build something in ANSI mode against a UNICODE build dnl of wxWidgets or in RELEASE mode against a DEBUG build of wxWidgets, dnl then at best you'll get ton of linking errors ! dnl ************************ ifelse(index([$1], [wxshared]), [-1],, [ WX_ARG_WITH_YESNOAUTO( [wxshared], [WX_SHARED], [Force building against a shared build of wxWidgets, even if --disable-shared is given], [auto], [], [1]) ]) dnl Just like for SHARED and WX_SHARED it may happen that some adventurous dnl peoples will want to mix a wxWidgets release build with a debug build of dnl his app/lib. So, we have both DEBUG and WX_DEBUG variables. ifelse(index([$1], [wxdebug]), [-1],, [ WX_ARG_WITH_YESNOAUTO( [wxdebug], [WX_DEBUG], [Force building against a debug build of wxWidgets, even if --disable-debug is given], [auto], [], [1]) ]) dnl WX_ARG_WITH_YESNOAUTO cannot be used for --with-wxversion since it's an option dnl which accepts the "auto|2.6|2.7|2.8|2.9|3.0" etc etc values ifelse(index([$1], [wxversion]), [-1],, [ AC_ARG_WITH([wxversion], AC_HELP_STRING([--with-wxversion], [Build against a specific version of wxWidgets (default is auto)]), [], [withval="auto"]) dnl Show a message to the user about this option AC_MSG_CHECKING([for the --with-wxversion option]) if test "$withval" = "auto" ; then AC_MSG_RESULT([will be automatically detected]) WX_RELEASE="auto" else wx_requested_major_version=`echo $withval | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).*/\1/'` wx_requested_minor_version=`echo $withval | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).*/\2/'` dnl both vars above must be exactly 1 digit if test "${#wx_requested_major_version}" != "1" -o \ "${#wx_requested_minor_version}" != "1" ; then AC_MSG_ERROR([ Unrecognized option value (allowed values: auto, 2.6, 2.7, 2.8, 2.9, 3.0) ]) fi WX_RELEASE="$wx_requested_major_version"".""$wx_requested_minor_version" AC_MSG_RESULT([$WX_RELEASE]) fi ]) if test "$WX_DEBUG_CONFIGURE" = "1"; then echo "[[dbg]] DEBUG: $DEBUG, WX_DEBUG: $WX_DEBUG" echo "[[dbg]] UNICODE: $UNICODE, WX_UNICODE: $WX_UNICODE" echo "[[dbg]] SHARED: $SHARED, WX_SHARED: $WX_SHARED" echo "[[dbg]] TOOLKIT: $TOOLKIT, WX_TOOLKIT: $WX_TOOLKIT" echo "[[dbg]] VERSION: $VERSION, WX_RELEASE: $WX_RELEASE" fi ]) dnl --------------------------------------------------------------------------- dnl WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS dnl dnl Sets the WXCONFIG_FLAGS string using the SHARED,DEBUG,UNICODE variable values dnl which are different from "auto". dnl Thus this macro needs to be called only once all options have been set. dnl --------------------------------------------------------------------------- AC_DEFUN([WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS], [ if test "$WX_SHARED" = "1" ; then WXCONFIG_FLAGS="--static=no " elif test "$WX_SHARED" = "0" ; then WXCONFIG_FLAGS="--static=yes " fi if test "$WX_DEBUG" = "1" ; then WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--debug=yes " elif test "$WX_DEBUG" = "0" ; then WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--debug=no " fi dnl The user should have set WX_UNICODE=UNICODE if test "$WX_UNICODE" = "1" ; then WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--unicode=yes " elif test "$WX_UNICODE" = "0" ; then WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--unicode=no " fi if test "$TOOLKIT" != "auto" ; then WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--toolkit=$TOOLKIT " fi if test "$WX_RELEASE" != "auto" ; then WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--version=$WX_RELEASE " fi dnl strip out the last space of the string WXCONFIG_FLAGS=${WXCONFIG_FLAGS% } if test "$WX_DEBUG_CONFIGURE" = "1"; then echo "[[dbg]] WXCONFIG_FLAGS: $WXCONFIG_FLAGS" fi ]) dnl --------------------------------------------------------------------------- dnl _WX_SELECTEDCONFIG_CHECKFOR([RESULTVAR], [STRING], [MSG] dnl [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) dnl dnl Outputs the given MSG. Then searches the given STRING in the wxWidgets dnl additional CPP flags and put the result of the search in WX_$RESULTVAR dnl also adding the "yes" or "no" message result to MSG. dnl --------------------------------------------------------------------------- AC_DEFUN([_WX_SELECTEDCONFIG_CHECKFOR], [ if test "$$1" = "auto" ; then dnl The user does not have particular preferences for this option; dnl so we will detect the wxWidgets relative build setting and use it AC_MSG_CHECKING([$3]) dnl set WX_$1 variable to 1 if the $WX_SELECTEDCONFIG contains the $2 dnl string or to 0 otherwise. dnl NOTE: 'expr match STRING REGEXP' cannot be used since on Mac it dnl doesn't work; we use 'expr STRING : REGEXP' instead WX_$1=$(expr "$WX_SELECTEDCONFIG" : ".*$2.*") if test "$WX_$1" != "0"; then WX_$1=1 AC_MSG_RESULT([yes]) ifelse([$4], , :, [$4]) else WX_$1=0 AC_MSG_RESULT([no]) ifelse([$5], , :, [$5]) fi else dnl Use the setting given by the user WX_$1=$$1 fi ]) dnl --------------------------------------------------------------------------- dnl WX_DETECT_STANDARD_OPTION_VALUES dnl dnl Detects the values of the following variables: dnl 1) WX_RELEASE dnl 2) WX_UNICODE dnl 3) WX_DEBUG dnl 4) WX_SHARED (and also WX_STATIC) dnl 5) WX_PORT dnl from the previously selected wxWidgets build; this macro in fact must be dnl called *after* calling the WX_CONFIG_CHECK macro. dnl dnl Note that the WX_VERSION_MAJOR, WX_VERSION_MINOR symbols are already set dnl by WX_CONFIG_CHECK macro dnl --------------------------------------------------------------------------- AC_DEFUN([WX_DETECT_STANDARD_OPTION_VALUES], [ dnl IMPORTANT: WX_VERSION contains all three major.minor.micro digits, dnl while WX_RELEASE only the major.minor ones. WX_RELEASE="$WX_VERSION_MAJOR""$WX_VERSION_MINOR" if test $WX_RELEASE -lt 26 ; then AC_MSG_ERROR([ Cannot detect the wxWidgets configuration for the selected wxWidgets build since its version is $WX_VERSION < 2.6.0; please install a newer version of wxWidgets. ]) fi dnl The wx-config we are using understands the "--selected_config" dnl option which returns an easy-parseable string ! WX_SELECTEDCONFIG=$($WX_CONFIG_WITH_ARGS --selected_config) if test "$WX_DEBUG_CONFIGURE" = "1"; then echo "[[dbg]] Using wx-config --selected-config" echo "[[dbg]] WX_SELECTEDCONFIG: $WX_SELECTEDCONFIG" fi dnl we could test directly for WX_SHARED with a line like: dnl _WX_SELECTEDCONFIG_CHECKFOR([SHARED], [shared], dnl [if wxWidgets was built in SHARED mode]) dnl but wx-config --selected-config DOES NOT outputs the 'shared' dnl word when wx was built in shared mode; it rather outputs the dnl 'static' word when built in static mode. if test $WX_SHARED = "1"; then STATIC=0 elif test $WX_SHARED = "0"; then STATIC=1 elif test $WX_SHARED = "auto"; then STATIC="auto" fi dnl Now set the WX_UNICODE, WX_DEBUG, WX_STATIC variables _WX_SELECTEDCONFIG_CHECKFOR([UNICODE], [unicode], [if wxWidgets was built with UNICODE enabled]) _WX_SELECTEDCONFIG_CHECKFOR([DEBUG], [debug], [if wxWidgets was built in DEBUG mode]) _WX_SELECTEDCONFIG_CHECKFOR([STATIC], [static], [if wxWidgets was built in STATIC mode]) dnl init WX_SHARED from WX_STATIC if test "$WX_STATIC" != "0"; then WX_SHARED=0 else WX_SHARED=1 fi AC_SUBST(WX_UNICODE) AC_SUBST(WX_DEBUG) AC_SUBST(WX_SHARED) dnl detect the WX_PORT to use if test "$TOOLKIT" = "auto" ; then dnl The user does not have particular preferences for this option; dnl so we will detect the wxWidgets relative build setting and use it AC_MSG_CHECKING([which wxWidgets toolkit was selected]) WX_GTKPORT1=$(expr "$WX_SELECTEDCONFIG" : ".*gtk1.*") WX_GTKPORT2=$(expr "$WX_SELECTEDCONFIG" : ".*gtk2.*") WX_MSWPORT=$(expr "$WX_SELECTEDCONFIG" : ".*msw.*") WX_MOTIFPORT=$(expr "$WX_SELECTEDCONFIG" : ".*motif.*") WX_OSXCOCOAPORT=$(expr "$WX_SELECTEDCONFIG" : ".*osx_cocoa.*") WX_OSXCARBONPORT=$(expr "$WX_SELECTEDCONFIG" : ".*osx_carbon.*") WX_X11PORT=$(expr "$WX_SELECTEDCONFIG" : ".*x11.*") WX_DFBPORT=$(expr "$WX_SELECTEDCONFIG" : ".*dfb.*") WX_PORT="unknown" if test "$WX_GTKPORT1" != "0"; then WX_PORT="gtk1"; fi if test "$WX_GTKPORT2" != "0"; then WX_PORT="gtk2"; fi if test "$WX_MSWPORT" != "0"; then WX_PORT="msw"; fi if test "$WX_MOTIFPORT" != "0"; then WX_PORT="motif"; fi if test "$WX_OSXCOCOAPORT" != "0"; then WX_PORT="osx_cocoa"; fi if test "$WX_OSXCARBONPORT" != "0"; then WX_PORT="osx_carbon"; fi if test "$WX_X11PORT" != "0"; then WX_PORT="x11"; fi if test "$WX_DFBPORT" != "0"; then WX_PORT="dfb"; fi dnl NOTE: backward-compatible check for wx2.8; in wx2.9 the mac dnl ports are called 'osx_cocoa' and 'osx_carbon' (see above) WX_MACPORT=$(expr "$WX_SELECTEDCONFIG" : ".*mac.*") if test "$WX_MACPORT" != "0"; then WX_PORT="mac"; fi dnl check at least one of the WX_*PORT has been set ! if test "$WX_PORT" = "unknown" ; then AC_MSG_ERROR([ Cannot detect the currently installed wxWidgets port ! Please check your 'wx-config --cxxflags'... ]) fi AC_MSG_RESULT([$WX_PORT]) else dnl Use the setting given by the user if test -z "$TOOLKIT" ; then WX_PORT=$TOOLKIT else dnl try with PORT WX_PORT=$PORT fi fi AC_SUBST(WX_PORT) if test "$WX_DEBUG_CONFIGURE" = "1"; then echo "[[dbg]] Values of all WX_* options after final detection:" echo "[[dbg]] WX_DEBUG: $WX_DEBUG" echo "[[dbg]] WX_UNICODE: $WX_UNICODE" echo "[[dbg]] WX_SHARED: $WX_SHARED" echo "[[dbg]] WX_RELEASE: $WX_RELEASE" echo "[[dbg]] WX_PORT: $WX_PORT" fi dnl Avoid problem described in the WX_STANDARD_OPTIONS which happens when dnl the user gives the options: dnl ./configure --enable-shared --without-wxshared dnl or just do dnl ./configure --enable-shared dnl but there is only a static build of wxWidgets available. if test "$WX_SHARED" = "0" -a "$SHARED" = "1"; then AC_MSG_ERROR([ Cannot build shared library against a static build of wxWidgets ! This error happens because the wxWidgets build which was selected has been detected as static while you asked to build $PACKAGE_NAME as shared library and this is not possible. Use the '--disable-shared' option to build $PACKAGE_NAME as static library or '--with-wxshared' to use wxWidgets as shared library. ]) fi dnl now we can finally update the DEBUG,UNICODE,SHARED options dnl to their final values if they were set to 'auto' if test "$DEBUG" = "auto"; then DEBUG=$WX_DEBUG fi if test "$UNICODE" = "auto"; then UNICODE=$WX_UNICODE fi if test "$SHARED" = "auto"; then SHARED=$WX_SHARED fi if test "$TOOLKIT" = "auto"; then TOOLKIT=$WX_PORT fi dnl in case the user needs a BUILD=debug/release var... if test "$DEBUG" = "1"; then BUILD="debug" elif test "$DEBUG" = "0" -o "$DEBUG" = ""; then BUILD="release" fi dnl respect the DEBUG variable adding the optimize/debug flags dnl NOTE: the CXXFLAGS are merged together with the CPPFLAGS so we dnl don't need to set them, too if test "$DEBUG" = "1"; then CXXFLAGS="$CXXFLAGS -g -O0" CFLAGS="$CFLAGS -g -O0" else CXXFLAGS="$CXXFLAGS -O2" CFLAGS="$CFLAGS -O2" fi ]) dnl --------------------------------------------------------------------------- dnl WX_BOOLOPT_SUMMARY([name of the boolean variable to show summary for], dnl [what to print when var is 1], dnl [what to print when var is 0]) dnl dnl Prints $2 when variable $1 == 1 and prints $3 when variable $1 == 0. dnl This macro mainly exists just to make configure.ac scripts more readable. dnl dnl NOTE: you need to use the [" my message"] syntax for 2nd and 3rd arguments dnl if you want that m4 avoid to throw away the spaces prefixed to the dnl argument value. dnl --------------------------------------------------------------------------- AC_DEFUN([WX_BOOLOPT_SUMMARY], [ if test "x$$1" = "x1" ; then echo $2 elif test "x$$1" = "x0" ; then echo $3 else echo "$1 is $$1" fi ]) dnl --------------------------------------------------------------------------- dnl WX_STANDARD_OPTIONS_SUMMARY_MSG dnl dnl Shows a summary message to the user about the WX_* variable contents. dnl This macro is used typically at the end of the configure script. dnl --------------------------------------------------------------------------- AC_DEFUN([WX_STANDARD_OPTIONS_SUMMARY_MSG], [ echo echo " The wxWidgets build which will be used by $PACKAGE_NAME $PACKAGE_VERSION" echo " has the following settings:" WX_BOOLOPT_SUMMARY([WX_DEBUG], [" - DEBUG build"], [" - RELEASE build"]) WX_BOOLOPT_SUMMARY([WX_UNICODE], [" - UNICODE mode"], [" - ANSI mode"]) WX_BOOLOPT_SUMMARY([WX_SHARED], [" - SHARED mode"], [" - STATIC mode"]) echo " - VERSION: $WX_VERSION" echo " - PORT: $WX_PORT" ]) dnl --------------------------------------------------------------------------- dnl WX_STANDARD_OPTIONS_SUMMARY_MSG_BEGIN, WX_STANDARD_OPTIONS_SUMMARY_MSG_END dnl dnl Like WX_STANDARD_OPTIONS_SUMMARY_MSG macro but these two macros also gives info dnl about the configuration of the package which used the wxpresets. dnl dnl Typical usage: dnl WX_STANDARD_OPTIONS_SUMMARY_MSG_BEGIN dnl echo " - Package setting 1: $SETTING1" dnl echo " - Package setting 2: $SETTING1" dnl ... dnl WX_STANDARD_OPTIONS_SUMMARY_MSG_END dnl dnl --------------------------------------------------------------------------- AC_DEFUN([WX_STANDARD_OPTIONS_SUMMARY_MSG_BEGIN], [ echo echo " ----------------------------------------------------------------" echo " Configuration for $PACKAGE_NAME $PACKAGE_VERSION successfully completed." echo " Summary of main configuration settings for $PACKAGE_NAME:" WX_BOOLOPT_SUMMARY([DEBUG], [" - DEBUG build"], [" - RELEASE build"]) WX_BOOLOPT_SUMMARY([UNICODE], [" - UNICODE mode"], [" - ANSI mode"]) WX_BOOLOPT_SUMMARY([SHARED], [" - SHARED mode"], [" - STATIC mode"]) ]) AC_DEFUN([WX_STANDARD_OPTIONS_SUMMARY_MSG_END], [ WX_STANDARD_OPTIONS_SUMMARY_MSG echo echo " Now, just run make." echo " ----------------------------------------------------------------" echo ]) dnl --------------------------------------------------------------------------- dnl Deprecated macro wrappers dnl --------------------------------------------------------------------------- AC_DEFUN([AM_OPTIONS_WXCONFIG], [WX_CONFIG_OPTIONS]) AC_DEFUN([AM_PATH_WXCONFIG], [ WX_CONFIG_CHECK([$1],[$2],[$3],[$4],[$5]) ]) AC_DEFUN([AM_PATH_WXRC], [WXRC_CHECK([$1],[$2])]) 07070100000008000081A4000003E800000064000000016039353E0000156F000000000000000000000000000000000000001B00000000diff-pdf-0.5/bmpviewer.cpp/* * This file is part of diff-pdf. * * Copyright (C) 2009 TT-Solutions. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "bmpviewer.h" #include "gutter.h" #include <wx/sizer.h> BEGIN_EVENT_TABLE(BitmapViewer, wxScrolledWindow) EVT_LEFT_DOWN(BitmapViewer::OnMouseDown) EVT_LEFT_UP(BitmapViewer::OnMouseUp) EVT_MOTION(BitmapViewer::OnMouseMove) EVT_MOUSE_CAPTURE_LOST(BitmapViewer::OnMouseCaptureLost) EVT_SCROLLWIN(BitmapViewer::OnScrolling) EVT_SIZE(BitmapViewer::OnSizeChanged) END_EVENT_TABLE() BitmapViewer::BitmapViewer(wxWindow *parent) : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE) { m_gutter = NULL; m_zoom_factor = 1.0; SetScrollRate(1, 1); wxBitmap dummyBitmap(16, 16); m_content = new wxStaticBitmap(this, wxID_ANY, dummyBitmap); wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(m_content, wxSizerFlags(1).Expand()); SetSizer(sizer); // we need to bind mouse-down event to m_content, as this scrolled window // will never see mouse events otherwise m_content->Connect ( wxEVT_LEFT_DOWN, wxMouseEventHandler(BitmapViewer::OnMouseDown), NULL, this ); } void BitmapViewer::SetBestFitZoom() { // compute highest scale factor that still doesn't need scrollbars: float scale_x = float(GetSize().x) / float(m_orig_image.GetWidth()); float scale_y = float(GetSize().y) / float(m_orig_image.GetHeight()); SetZoom(std::min(scale_x, scale_y)); } void BitmapViewer::UpdateBitmap() { int new_w = int(m_orig_image.GetWidth() * m_zoom_factor); int new_h = int(m_orig_image.GetHeight() * m_zoom_factor); if ( new_w != m_orig_image.GetWidth() || new_h != m_orig_image.GetHeight() ) { wxImage scaled = m_orig_image.Scale ( new_w, new_h, // we don't need HQ filtering when upscaling m_zoom_factor < 1.0 ? wxIMAGE_QUALITY_HIGH : wxIMAGE_QUALITY_NORMAL ); m_content->SetBitmap(wxBitmap(scaled)); } else { m_content->SetBitmap(wxBitmap(m_orig_image)); } GetSizer()->FitInside(this); if ( m_gutter ) m_gutter->UpdateViewPos(this); } void BitmapViewer::Set(const wxImage& image) { m_orig_image = image; UpdateBitmap(); } void BitmapViewer::Set(cairo_surface_t *surface) { // Cairo's RGB24 surfaces use 32 bits per pixel, while wxImage uses // 24 bits per pixel, so we need to convert between the two representations // manually. Moreover, channels order is different too, RGB vs. BGR. const int w = cairo_image_surface_get_width(surface); const int h = cairo_image_surface_get_height(surface); wxImage img(w, h, false); unsigned char *p_out = img.GetData(); const unsigned char *p_in = cairo_image_surface_get_data(surface); const int stride = cairo_image_surface_get_stride(surface); for ( int y = 0; y < h; y++, p_in += stride ) { for ( int x = 0; x < w; x++ ) { *(p_out++) = *(p_in + 4 * x + 2); *(p_out++) = *(p_in + 4 * x + 1); *(p_out++) = *(p_in + 4 * x + 0); } } Set(img); } void BitmapViewer::AttachGutter(Gutter *g) { m_gutter = g; if ( g ) g->UpdateViewPos(this); } void BitmapViewer::OnMouseDown(wxMouseEvent& event) { wxPoint view_origin; GetViewStart(&view_origin.x, &view_origin.y); const wxPoint pos = event.GetPosition(); m_draggingPage = true; m_draggingLastMousePos = pos; CaptureMouse(); } void BitmapViewer::OnMouseUp(wxMouseEvent&) { m_draggingPage = false; ReleaseMouse(); } void BitmapViewer::OnMouseMove(wxMouseEvent& event) { event.Skip(); if ( !m_draggingPage ) return; wxPoint view_origin; GetViewStart(&view_origin.x, &view_origin.y); const wxPoint pos = event.GetPosition(); wxPoint new_pos = view_origin + (m_draggingLastMousePos - pos); Scroll(new_pos.x, new_pos.y); if ( m_gutter ) m_gutter->UpdateViewPos(this); m_draggingLastMousePos = pos; } void BitmapViewer::OnMouseCaptureLost(wxMouseCaptureLostEvent& event) { m_draggingPage = false; event.Skip(); } void BitmapViewer::OnScrolling(wxScrollWinEvent& event) { if ( m_gutter ) m_gutter->UpdateViewPos(this); event.Skip(); } void BitmapViewer::OnSizeChanged(wxSizeEvent& event) { if ( m_gutter ) m_gutter->UpdateViewPos(this); event.Skip(); } 07070100000009000081A4000003E800000064000000016039353E000008DE000000000000000000000000000000000000001900000000diff-pdf-0.5/bmpviewer.h/* * This file is part of diff-pdf. * * Copyright (C) 2009 TT-Solutions. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef _bmpviewer_h_ #define _bmpviewer_h_ #include <cairo/cairo.h> #include <wx/image.h> #include <wx/bitmap.h> #include <wx/statbmp.h> #include <wx/scrolwin.h> #include <wx/event.h> class Gutter; // widget for comfortable viewing of a bitmap, with high-quality zooming class BitmapViewer : public wxScrolledWindow { public: BitmapViewer(wxWindow *parent); // set the bitmap to be shown void Set(const wxImage& image); void Set(cairo_surface_t *surface); float GetZoom() const { return m_zoom_factor; } void SetZoom(float factor) { m_zoom_factor = factor; UpdateBitmap(); } // sets the zoom value to "best fit" for current window size void SetBestFitZoom(); // attaches a gutter that shows current scrolling position to the window void AttachGutter(Gutter *g); private: // update the content after some change (bitmap, zoom factor, ...) void UpdateBitmap(); void OnMouseDown(wxMouseEvent& event); void OnMouseUp(wxMouseEvent& event); void OnMouseMove(wxMouseEvent& event); void OnMouseCaptureLost(wxMouseCaptureLostEvent& event); void OnScrolling(wxScrollWinEvent& event); void OnSizeChanged(wxSizeEvent& event); private: wxStaticBitmap *m_content; wxImage m_orig_image; float m_zoom_factor; // is the user currently dragging the page around with the mouse? bool m_draggingPage; wxPoint m_draggingLastMousePos; Gutter *m_gutter; DECLARE_EVENT_TABLE() }; #endif // _bmpviewer_h_ 0707010000000A000081ED000003E800000064000000016039353E00000A26000000000000000000000000000000000000001700000000diff-pdf-0.5/bootstrap#!/bin/sh # Script to execute to initialize diff-pdf build system after checking out # pristine sources from a version control system: this script creates all # generated files which are needed for the build but not stored under version # control. # Copyright (C) 2005, 2006, 2007, 2008 Vadim Zeitlin # All Rights Reserved # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # 3. Neither the name of the Author nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR # OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # $Id$ if [ ! -f configure.ac -o ! -f Makefile.am ]; then echo "Please run this script from the diff-pdf source directory." exit 2 fi # use --foreign with automake because we lack standard GNU NEWS and AUTHOR # files, if they're added we can "upgrade" to (default) GNU strictness. Use # --copy to allow simultaneous use on windows under mingw and cygwin platforms. # Symlinking of files under mingw does not work out for cygwin and vice-versa. echo "Setting up build system for diff-pdf:" echo " - aclocal " && aclocal ${wx+-I} $wx -I admin && \ echo " - autoconf " && autoconf && \ echo " - automake " && automake --add-missing --copy --foreign && \ echo "Build setup successful, type \"./configure\" to configure diff-pdf now." && \ exit 0 echo "Automatic build files setup failed!" exit 1 0707010000000B000081A4000003E800000064000000016039353E00000607000000000000000000000000000000000000001A00000000diff-pdf-0.5/configure.ac dnl This file is part of diff-pdf. dnl dnl Copyright (C) 2009 TT-Solutions. dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program. If not, see <http://www.gnu.org/licenses/>. AC_PREREQ(2.61) AC_INIT(diff-pdf, 0.5, [vaclav@slavik.io]) AC_CONFIG_SRCDIR([diff-pdf.cpp]) AC_CONFIG_AUX_DIR([admin]) AM_INIT_AUTOMAKE AM_MAINTAINER_MODE m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) dnl remember, "build" is where we compile, "host" is where the resulting dnl program runs (which may be different from "build" for cross-compilation) AC_CANONICAL_HOST dnl === Program checks === AC_PROG_CXX AC_LANG(C++) dnl === Library checks === PKG_CHECK_MODULES(POPPLER, [glib-2.0 >= 2.36 poppler-glib >= 0.10 cairo-pdf]) AM_OPTIONS_WXCONFIG AM_PATH_WXCONFIG([3.0.0], [wxfound=1], [wxfound=0], [core,base]) if test "$wxfound" != 1 ; then AC_MSG_ERROR([wxWidgets is required]) fi dnl === Generate output files === AC_CONFIG_FILES([ Makefile ]) AC_OUTPUT 0707010000000C000081A4000003E800000064000000016039353E00007A8A000000000000000000000000000000000000001A00000000diff-pdf-0.5/diff-pdf.cpp/* * This file is part of diff-pdf. * * Copyright (C) 2009 TT-Solutions. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "bmpviewer.h" #include "gutter.h" #include <stdio.h> #include <assert.h> #include <vector> #include <glib.h> #include <poppler.h> #include <cairo/cairo.h> #include <cairo/cairo-pdf.h> #include <wx/app.h> #include <wx/evtloop.h> #include <wx/cmdline.h> #include <wx/filename.h> #include <wx/log.h> #include <wx/frame.h> #include <wx/sizer.h> #include <wx/toolbar.h> #include <wx/artprov.h> #include <wx/progdlg.h> #include <wx/filesys.h> // ------------------------------------------------------------------------ // PDF rendering functions // ------------------------------------------------------------------------ bool g_verbose = false; bool g_skip_identical = false; bool g_mark_differences = false; long g_channel_tolerance = 0; bool g_grayscale = false; // Resolution to use for rasterization, in DPI #define DEFAULT_RESOLUTION 300 long g_resolution = DEFAULT_RESOLUTION; inline unsigned char to_grayscale(unsigned char r, unsigned char g, unsigned char b) { return (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b); } cairo_surface_t *render_page(PopplerPage *page) { double w, h; poppler_page_get_size(page, &w, &h); const int w_px = int((int)g_resolution * w / 72.0); const int h_px = int((int)g_resolution * h / 72.0); cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w_px, h_px); cairo_t *cr = cairo_create(surface); // clear the surface to white background: cairo_save(cr); cairo_set_source_rgb(cr, 1, 1, 1); cairo_rectangle(cr, 0, 0, w_px, h_px); cairo_fill(cr); cairo_restore(cr); // Scale so that PDF output covers the whole surface. Image surface is // created with transformation set up so that 1 coordinate unit is 1 pixel; // Poppler assumes 1 unit = 1 point. cairo_scale(cr, (int)g_resolution / 72.0, (int)g_resolution / 72.0); poppler_page_render(page, cr); cairo_show_page(cr); cairo_destroy(cr); return surface; } // Creates image of differences between s1 and s2. If the offset is specified, // then s2 is displaced by it. If thumbnail and thumbnail_width are specified, // then a thumbnail with highlighted differences is created too. cairo_surface_t *diff_images(cairo_surface_t *s1, cairo_surface_t *s2, int offset_x = 0, int offset_y = 0, wxImage *thumbnail = NULL, int thumbnail_width = -1) { assert( s1 || s2 ); wxRect r1, r2; if ( s1 ) { r1 = wxRect(0, 0, cairo_image_surface_get_width(s1), cairo_image_surface_get_height(s1)); } if ( s2 ) { r2 = wxRect(offset_x, offset_y, cairo_image_surface_get_width(s2), cairo_image_surface_get_height(s2)); } // compute union rectangle starting at [0,0] position wxRect rdiff(r1); rdiff.Union(r2); r1.Offset(-rdiff.x, -rdiff.y); r2.Offset(-rdiff.x, -rdiff.y); rdiff.Offset(-rdiff.x, -rdiff.y); bool changes = false; cairo_surface_t *diff = cairo_image_surface_create(CAIRO_FORMAT_RGB24, rdiff.width, rdiff.height); float thumbnail_scale; int thumbnail_height; if ( thumbnail ) { thumbnail_scale = float(thumbnail_width) / float(rdiff.width); thumbnail_height = int(rdiff.height * thumbnail_scale); thumbnail->Create(thumbnail_width, thumbnail_height); // initalize the thumbnail with a white rectangle: thumbnail->SetRGB(wxRect(), 255, 255, 255); } // clear the surface to white background if the merged images don't fully // overlap: if ( r1 != r2 ) { changes = true; cairo_t *cr = cairo_create(diff); cairo_set_source_rgb(cr, 1, 1, 1); cairo_rectangle(cr, 0, 0, rdiff.width, rdiff.height); cairo_fill(cr); cairo_destroy(cr); } const int stride1 = s1 ? cairo_image_surface_get_stride(s1) : 0; const int stride2 = s2 ? cairo_image_surface_get_stride(s2) : 0; const int stridediff = cairo_image_surface_get_stride(diff); const unsigned char *data1 = s1 ? cairo_image_surface_get_data(s1) : NULL; const unsigned char *data2 = s2 ? cairo_image_surface_get_data(s2) : NULL; unsigned char *datadiff = cairo_image_surface_get_data(diff); // we visualize the differences by taking one channel from s1 // and the other two channels from s2: // first, copy s1 over: if ( s1 ) { unsigned char *out = datadiff + r1.y * stridediff + r1.x * 4; for ( int y = 0; y < r1.height; y++, data1 += stride1, out += stridediff ) { memcpy(out, data1, r1.width * 4); } } // then, copy B channel from s2 over it; also compare the two versions // to see if there are any differences: if ( s2 ) { unsigned char *out = datadiff + r2.y * stridediff + r2.x * 4; for ( int y = 0; y < r2.height; y++, data2 += stride2, out += stridediff ) { bool linediff = false; for ( int x = 0; x < r2.width * 4; x += 4 ) { unsigned char cr1 = *(out + x + 0); unsigned char cg1 = *(out + x + 1); unsigned char cb1 = *(out + x + 2); unsigned char cr2 = *(data2 + x + 0); unsigned char cg2 = *(data2 + x + 1); unsigned char cb2 = *(data2 + x + 2); if ( cr1 > (cr2+g_channel_tolerance) || cr1 < (cr2-g_channel_tolerance) || cg1 > (cg2+g_channel_tolerance) || cg1 < (cg2-g_channel_tolerance) || cb1 > (cb2+g_channel_tolerance) || cb1 < (cb2-g_channel_tolerance) ) { changes = true; linediff = true; if ( thumbnail ) { // calculate the coordinates in the thumbnail int tx = int((r2.x + x/4.0) * thumbnail_scale); int ty = int((r2.y + y) * thumbnail_scale); // Limit the coordinates to the thumbnail size (may be // off slightly due to rounding errors). // See https://github.com/vslavik/diff-pdf/pull/58 tx = std::min(tx, thumbnail_width - 1); ty = std::min(ty, thumbnail_height - 1); // mark changes with red thumbnail->SetRGB(tx, ty, 255, 0, 0); } } if (g_grayscale) { // convert both images to grayscale, use blue for s1, red for s2 unsigned char gray1 = to_grayscale(cr1, cg1, cb1); unsigned char gray2 = to_grayscale(cr2, cg2, cb2); *(out + x + 0) = gray2; *(out + x + 1) = (gray1 + gray2) / 2; *(out + x + 2) = gray1; } else { // change the B channel to be from s2; RG will be s1 *(out + x + 2) = cb2; } } if (g_mark_differences && linediff) { for (int x = 0; x < (10 < r2.width ? 10 : r2.width) * 4; x+=4) { *(out + x + 0) = 0; *(out + x + 1) = 0; *(out + x + 2) = 255; } } } } // add background image of the page to the thumbnails if ( thumbnail ) { // copy the 'diff' surface into wxImage: wxImage bg(rdiff.width, rdiff.height); unsigned char *in = datadiff; unsigned char *out = bg.GetData(); for ( int y = 0; y < rdiff.height; y++, in += stridediff ) { for ( int x = 0; x < rdiff.width * 4; x += 4 ) { // cairo_surface_t uses BGR order, wxImage has RGB *(out++) = *(in + x + 2); *(out++) = *(in + x + 1); *(out++) = *(in + x + 0); } } // scale it to thumbnail size: bg.Rescale(thumbnail_width, thumbnail_height, wxIMAGE_QUALITY_HIGH); // and merge with the diff markers in *thumbnail, making it much // lighter in the process: in = bg.GetData(); out = thumbnail->GetData(); for ( int i = thumbnail_width * thumbnail_height; i > 0; i-- ) { if ( out[1] == 0 ) // G=0 ==> not white { // marked with red color, as place with differences -- don't // paint background image here, make the red as visible as // possible out += 3; in += 3; } else { // merge in lighter background image *(out++) = 128 + *(in++) / 2; *(out++) = 128 + *(in++) / 2; *(out++) = 128 + *(in++) / 2; } } // If there were no changes, indicate it by using green // (170,230,130) color for the thumbnail in gutter control: if ( !changes ) { out = thumbnail->GetData(); for ( int i = thumbnail_width * thumbnail_height; i > 0; i--, out += 3 ) { out[0] = 170/2 + out[0] / 2; out[1] = 230/2 + out[1] / 2; out[2] = 130/2 + out[2] / 2; } } } if ( changes ) { return diff; } else { cairo_surface_destroy(diff); return NULL; } } // Compares given two pages. If cr_out is not NULL, then the diff image (either // differences or unmodified page, if there are no diffs) is drawn to it. // If thumbnail and thumbnail_width are specified, then a thumbnail with // highlighted differences is created too. bool page_compare(cairo_t *cr_out, PopplerPage *page1, PopplerPage *page2, wxImage *thumbnail = NULL, int thumbnail_width = -1) { cairo_surface_t *img1 = page1 ? render_page(page1) : NULL; cairo_surface_t *img2 = page2 ? render_page(page2) : NULL; cairo_surface_t *diff = diff_images(img1, img2, 0, 0, thumbnail, thumbnail_width); const bool has_diff = (diff != NULL); if ( cr_out ) { if ( diff ) { // render the difference as high-resolution bitmap cairo_save(cr_out); cairo_scale(cr_out, 72.0 / g_resolution, 72.0 / g_resolution); cairo_set_source_surface(cr_out, diff ? diff : img1, 0, 0); cairo_paint(cr_out); cairo_restore(cr_out); } else { // save space (as well as improve rendering quality) in diff pdf // by writing unchanged pages in their original form rather than // a rasterized one if (!g_skip_identical) poppler_page_render(page1, cr_out); } if (diff || !g_skip_identical) cairo_show_page(cr_out); } if ( diff ) cairo_surface_destroy(diff); if ( img1 ) cairo_surface_destroy(img1); if ( img2 ) cairo_surface_destroy(img2); return !has_diff; } // Compares two documents, writing diff PDF into file named 'pdf_output' if // not NULL. if 'differences' is not NULL, puts a map of which pages differ // into it. If 'progress' is provided, it is updated to reflect comparison's // progress. If 'gutter' is set, then all the pages are added to it, with // their respective thumbnails (the gutter must be empty beforehand). bool doc_compare(PopplerDocument *doc1, PopplerDocument *doc2, const char *pdf_output, std::vector<bool> *differences, wxProgressDialog *progress = NULL, Gutter *gutter = NULL) { int pages_differ = 0; cairo_surface_t *surface_out = NULL; cairo_t *cr_out = NULL; if ( pdf_output ) { double w, h; poppler_page_get_size(poppler_document_get_page(doc1, 0), &w, &h); surface_out = cairo_pdf_surface_create(pdf_output, w, h); cr_out = cairo_create(surface_out); } int pages1 = poppler_document_get_n_pages(doc1); int pages2 = poppler_document_get_n_pages(doc2); int pages_total = pages1 > pages2 ? pages1 : pages2; if ( pages1 != pages2 ) { if ( g_verbose ) printf("pages count differs: %d vs %d\n", pages1, pages2); } for ( int page = 0; page < pages_total; page++ ) { if ( progress ) { progress->Update ( page, wxString::Format ( "Comparing page %d of %d...", page+1, pages_total ) ); } if ( pdf_output && page != 0 ) { double w, h; poppler_page_get_size(poppler_document_get_page(doc1, page), &w, &h); cairo_pdf_surface_set_size(surface_out, w, h); } PopplerPage *page1 = page < pages1 ? poppler_document_get_page(doc1, page) : NULL; PopplerPage *page2 = page < pages2 ? poppler_document_get_page(doc2, page) : NULL; bool page_same; if ( gutter ) { wxImage thumbnail; page_same = page_compare(cr_out, page1, page2, &thumbnail, Gutter::WIDTH); wxString label1("(null)"); wxString label2("(null)"); if ( page1 ) { gchar *label; g_object_get(page1, "label", &label, NULL); label1 = wxString::FromUTF8(label); g_free(label); } if ( page2 ) { gchar *label; g_object_get(page2, "label", &label, NULL); label2 = wxString::FromUTF8(label); g_free(label); } wxString label; if ( label1 == label2 ) label = label1; else label = label1 + " / " + label2; gutter->AddPage(label, thumbnail); } else { page_same = page_compare(cr_out, page1, page2); } if ( differences ) differences->push_back(!page_same); if ( !page_same ) { pages_differ ++; if ( g_verbose ) printf("page %d differs\n", page); // If we don't need to output all different pages in any // form (including verbose report of differing pages!), then // we can stop comparing the PDFs as soon as we find the first // difference. if ( !g_verbose && !pdf_output && !differences && !gutter ) break; } } if ( pdf_output ) { cairo_destroy(cr_out); cairo_surface_destroy(surface_out); } if (g_verbose) printf("%d of %d pages differ.\n", pages_differ, pages_total); // are doc1 and doc1 the same? return (pages_differ == 0) && (pages1 == pages2); } // ------------------------------------------------------------------------ // wxWidgets GUI // ------------------------------------------------------------------------ const int ID_PREV_PAGE = wxNewId(); const int ID_NEXT_PAGE = wxNewId(); const int ID_ZOOM_IN = wxNewId(); const int ID_ZOOM_OUT = wxNewId(); const int ID_OFFSET_LEFT = wxNewId(); const int ID_OFFSET_RIGHT = wxNewId(); const int ID_OFFSET_UP = wxNewId(); const int ID_OFFSET_DOWN = wxNewId(); const int ID_GUTTER = wxNewId(); #define BMP_ARTPROV(id) wxArtProvider::GetBitmap(id, wxART_TOOLBAR) #define BMP_PREV_PAGE BMP_ARTPROV(wxART_GO_BACK) #define BMP_NEXT_PAGE BMP_ARTPROV(wxART_GO_FORWARD) #define BMP_OFFSET_LEFT BMP_ARTPROV(wxART_GO_BACK) #define BMP_OFFSET_RIGHT BMP_ARTPROV(wxART_GO_FORWARD) #define BMP_OFFSET_UP BMP_ARTPROV(wxART_GO_UP) #define BMP_OFFSET_DOWN BMP_ARTPROV(wxART_GO_DOWN) #ifdef __WXGTK__ #define BMP_ZOOM_IN BMP_ARTPROV("gtk-zoom-in") #define BMP_ZOOM_OUT BMP_ARTPROV("gtk-zoom-out") #else #include "gtk-zoom-in.xpm" #include "gtk-zoom-out.xpm" #define BMP_ZOOM_IN wxBitmap(gtk_zoom_in_xpm) #define BMP_ZOOM_OUT wxBitmap(gtk_zoom_out_xpm) #endif static const float ZOOM_FACTOR_STEP = 1.2f; class DiffFrame : public wxFrame { public: DiffFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title) { m_cur_page = -1; CreateStatusBar(2); SetStatusBarPane(0); const int stat_widths[] = { -1, 150 }; SetStatusWidths(2, stat_widths); wxToolBar *toolbar = new wxToolBar ( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxTB_FLAT | wxTB_HORZ_TEXT ); toolbar->AddTool(ID_PREV_PAGE, "Previous", BMP_PREV_PAGE, "Go to previous page (PgUp)"); toolbar->AddTool(ID_NEXT_PAGE, "Next", BMP_NEXT_PAGE, "Go to next page (PgDown)"); toolbar->AddTool(ID_ZOOM_IN, "Zoom in", BMP_ZOOM_IN, "Make the page larger (Ctrl +)"); toolbar->AddTool(ID_ZOOM_OUT, "Zoom out", BMP_ZOOM_OUT, "Make the page smaller (Ctrl -)"); toolbar->AddTool(ID_OFFSET_LEFT, "", BMP_OFFSET_LEFT, "Offset one of the pages to the left (Ctrl left)"); toolbar->AddTool(ID_OFFSET_RIGHT, "", BMP_OFFSET_RIGHT, "Offset one of the pages to the right (Ctrl right)"); toolbar->AddTool(ID_OFFSET_UP, "", BMP_OFFSET_UP, "Offset one of the pages up (Ctrl up)"); toolbar->AddTool(ID_OFFSET_DOWN, "", BMP_OFFSET_DOWN, "Offset one of the pages down (Ctrl down)"); toolbar->Realize(); SetToolBar(toolbar); wxAcceleratorEntry accels[8]; accels[0].Set(wxACCEL_NORMAL, WXK_PAGEUP, ID_PREV_PAGE); accels[1].Set(wxACCEL_NORMAL, WXK_PAGEDOWN, ID_NEXT_PAGE); accels[2].Set(wxACCEL_CTRL, (int)'=', ID_ZOOM_IN); accels[3].Set(wxACCEL_CTRL, (int)'-', ID_ZOOM_OUT); accels[4].Set(wxACCEL_CTRL, WXK_LEFT, ID_OFFSET_LEFT); accels[5].Set(wxACCEL_CTRL, WXK_RIGHT, ID_OFFSET_RIGHT); accels[6].Set(wxACCEL_CTRL, WXK_UP, ID_OFFSET_UP); accels[7].Set(wxACCEL_CTRL, WXK_DOWN, ID_OFFSET_DOWN); wxAcceleratorTable accel_table(8, accels); SetAcceleratorTable(accel_table); m_gutter = new Gutter(this, ID_GUTTER); m_viewer = new BitmapViewer(this); m_viewer->AttachGutter(m_gutter); m_viewer->SetFocus(); wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(m_gutter, wxSizerFlags(0).Expand().Border(wxALL, 2)); sizer->Add(m_viewer, wxSizerFlags(1).Expand()); SetSizer(sizer); } void SetDocs(PopplerDocument *doc1, PopplerDocument *doc2) { m_doc1 = doc1; m_doc2 = doc2; wxProgressDialog progress("Comparing documents", "Comparing documents...", wxMax(poppler_document_get_n_pages(m_doc1), poppler_document_get_n_pages(m_doc2)), this, wxPD_SMOOTH | wxPD_REMAINING_TIME); doc_compare(m_doc1, m_doc2, NULL, &m_pages, &progress, m_gutter); progress.Pulse(); m_diff_count = 0; for ( std::vector<bool>::const_iterator i = m_pages.begin(); i != m_pages.end(); ++i ) { if ( *i ) m_diff_count++; } GoToPage(0); progress.Pulse(); m_viewer->SetBestFitZoom(); UpdateStatus(); progress.Hide(); } void GoToPage(int n) { m_cur_page = n; m_gutter->SetSelection(n); DoUpdatePage(); } private: void DoUpdatePage() { wxBusyCursor wait; const int pages1 = poppler_document_get_n_pages(m_doc1); const int pages2 = poppler_document_get_n_pages(m_doc2); PopplerPage *page1 = m_cur_page < pages1 ? poppler_document_get_page(m_doc1, m_cur_page) : NULL; PopplerPage *page2 = m_cur_page < pages2 ? poppler_document_get_page(m_doc2, m_cur_page) : NULL; cairo_surface_t *img1 = page1 ? render_page(page1) : NULL; cairo_surface_t *img2 = page2 ? render_page(page2) : NULL; wxImage thumbnail; cairo_surface_t *diff = diff_images ( img1, img2, m_offset.x, m_offset.y, &thumbnail, Gutter::WIDTH ); m_viewer->Set(diff ? diff : img1); // Always update the diff map. It will be all-white if there were // no differences. m_gutter->SetThumbnail(m_cur_page, thumbnail); if ( img1 ) cairo_surface_destroy(img1); if ( img2 ) cairo_surface_destroy(img2); if ( diff ) cairo_surface_destroy(diff); UpdateStatus(); } void UpdateStatus() { SetStatusText ( wxString::Format ( "Page %d of %d; %d of them %s different, this page %s", m_cur_page + 1 /* humans prefer 1-based counting*/, (int)m_pages.size(), m_diff_count, m_diff_count == 1 ? "is" : "are", m_pages[m_cur_page] ? "differs" : "is unchanged" ), 0 ); SetStatusText ( wxString::Format ( "%.1f%% [offset %d,%d]", m_viewer->GetZoom() * 100.0, m_offset.x, m_offset.y ), 1 ); } void OnSetPage(wxCommandEvent& event) { GoToPage(event.GetSelection()); } void OnPrevPage(wxCommandEvent&) { if ( m_cur_page > 0 ) GoToPage(m_cur_page - 1); } void OnNextPage(wxCommandEvent&) { if ( m_cur_page < m_pages.size() - 1 ) GoToPage(m_cur_page + 1); } void OnUpdatePrevPage(wxUpdateUIEvent& event) { event.Enable(m_cur_page > 0); } void OnUpdateNextPage(wxUpdateUIEvent& event) { event.Enable(m_cur_page < m_pages.size() - 1); } void OnZoomIn(wxCommandEvent&) { wxBusyCursor wait; m_viewer->SetZoom(m_viewer->GetZoom() * ZOOM_FACTOR_STEP); UpdateStatus(); } void OnZoomOut(wxCommandEvent&) { wxBusyCursor wait; m_viewer->SetZoom(m_viewer->GetZoom() / ZOOM_FACTOR_STEP); UpdateStatus(); } void DoOffset(int x, int y) { m_offset.x += x; m_offset.y += y; DoUpdatePage(); } void OnOffsetLeft(wxCommandEvent&) { DoOffset(-1, 0); } void OnOffsetRight(wxCommandEvent&) { DoOffset(1, 0); } void OnOffsetUp(wxCommandEvent&) { DoOffset(0, -1); } void OnOffsetDown(wxCommandEvent&) { DoOffset(0, 1); } DECLARE_EVENT_TABLE() private: BitmapViewer *m_viewer; Gutter *m_gutter; PopplerDocument *m_doc1, *m_doc2; std::vector<bool> m_pages; int m_diff_count; int m_cur_page; wxPoint m_offset; }; BEGIN_EVENT_TABLE(DiffFrame, wxFrame) EVT_LISTBOX (ID_GUTTER, DiffFrame::OnSetPage) EVT_TOOL (ID_PREV_PAGE, DiffFrame::OnPrevPage) EVT_TOOL (ID_NEXT_PAGE, DiffFrame::OnNextPage) EVT_UPDATE_UI(ID_PREV_PAGE, DiffFrame::OnUpdatePrevPage) EVT_UPDATE_UI(ID_NEXT_PAGE, DiffFrame::OnUpdateNextPage) EVT_TOOL (ID_ZOOM_IN, DiffFrame::OnZoomIn) EVT_TOOL (ID_ZOOM_OUT, DiffFrame::OnZoomOut) EVT_TOOL (ID_OFFSET_LEFT, DiffFrame::OnOffsetLeft) EVT_TOOL (ID_OFFSET_RIGHT, DiffFrame::OnOffsetRight) EVT_TOOL (ID_OFFSET_UP, DiffFrame::OnOffsetUp) EVT_TOOL (ID_OFFSET_DOWN, DiffFrame::OnOffsetDown) END_EVENT_TABLE() class DiffPdfApp : public wxApp { public: DiffPdfApp() : m_tlw(NULL) {} virtual bool OnInit() { m_tlw = new DiffFrame(m_title); // like in LMI, maximize the window m_tlw->Maximize(); m_tlw->Show(); // yield so that size changes above take effect immediately (and so we // can query the window for its size) Yield(); return true; } void SetData(const wxString& file1, PopplerDocument *doc1, const wxString& file2, PopplerDocument *doc2) { m_title = wxString::Format("Differences between %s and %s", file1.c_str(), file2.c_str()); m_doc1 = doc1; m_doc2 = doc2; } protected: virtual void OnEventLoopEnter(wxEventLoopBase *loop) { wxApp::OnEventLoopEnter(loop); if ( loop->IsMain() ) SetFrameDocs(); } void SetFrameDocs() { wxASSERT( m_tlw ); wxASSERT( m_doc1 ); wxASSERT( m_doc2 ); m_tlw->SetDocs(m_doc1, m_doc2); } private: DiffFrame *m_tlw; wxString m_title; PopplerDocument *m_doc1, *m_doc2; }; IMPLEMENT_APP_NO_MAIN(DiffPdfApp); // ------------------------------------------------------------------------ // main() // ------------------------------------------------------------------------ int main(int argc, char *argv[]) { wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "diff-pdf"); wxInitializer wxinitializer(argc, argv); static const wxCmdLineEntryDesc cmd_line_desc[] = { { wxCMD_LINE_SWITCH, "h", "help", "show this help message", wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, { wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" }, { wxCMD_LINE_SWITCH, "s", "skip-identical", "only output pages with differences" }, { wxCMD_LINE_SWITCH, "m", "mark-differences", "additionally mark differences on left side" }, { wxCMD_LINE_SWITCH, "g", "grayscale", "only differences will be in color, unchanged parts will show as gray" }, { wxCMD_LINE_OPTION, NULL, "output-diff", "output differences to given PDF file", wxCMD_LINE_VAL_STRING }, { wxCMD_LINE_OPTION, NULL, "channel-tolerance", "consider channel values to be equal if within specified tolerance", wxCMD_LINE_VAL_NUMBER }, { wxCMD_LINE_OPTION, NULL, "dpi", "rasterization resolution (default: " wxSTRINGIZE(DEFAULT_RESOLUTION) " dpi)", wxCMD_LINE_VAL_NUMBER }, { wxCMD_LINE_SWITCH, NULL, "view", "view the differences in a window" }, { wxCMD_LINE_PARAM, NULL, NULL, "file1.pdf", wxCMD_LINE_VAL_STRING }, { wxCMD_LINE_PARAM, NULL, NULL, "file2.pdf", wxCMD_LINE_VAL_STRING }, { wxCMD_LINE_NONE } }; wxCmdLineParser parser(cmd_line_desc, argc, argv); // Set default output to stderr wxMessageOutput::Set(new wxMessageOutputStderr); switch ( parser.Parse() ) { case -1: // --help return 0; case 0: // everything is ok; proceed break; default: // syntax error return 2; } if ( parser.Found("verbose") ) g_verbose = true; if ( parser.Found("skip-identical") ) g_skip_identical = true; if ( parser.Found("mark-differences") ) g_mark_differences = true; if ( parser.Found("grayscale") ) g_grayscale = true; wxFileName file1(parser.GetParam(0)); wxFileName file2(parser.GetParam(1)); file1.MakeAbsolute(); file2.MakeAbsolute(); const wxString url1 = wxFileSystem::FileNameToURL(file1); const wxString url2 = wxFileSystem::FileNameToURL(file2); GError *err = NULL; PopplerDocument *doc1 = poppler_document_new_from_file(url1.utf8_str(), NULL, &err); if ( !doc1 ) { fprintf(stderr, "Error opening %s: %s\n", (const char*) parser.GetParam(0).c_str(), err->message); g_error_free(err); return 3; } PopplerDocument *doc2 = poppler_document_new_from_file(url2.utf8_str(), NULL, &err); if ( !doc2 ) { fprintf(stderr, "Error opening %s: %s\n", (const char*) parser.GetParam(1).c_str(), err->message); g_error_free(err); return 3; } if ( parser.Found("channel-tolerance", &g_channel_tolerance) ) { if (g_channel_tolerance < 0 || g_channel_tolerance > 255) { fprintf(stderr, "Invalid channel-tolerance: %ld. Valid range is 0(default, exact matching)-255\n", g_channel_tolerance); return 2; } } if ( parser.Found("dpi", &g_resolution) ) { if (g_resolution < 1 || g_resolution > 2400) { fprintf(stderr, "Invalid dpi: %ld. Valid range is 1-2400 (default: %d)\n", g_resolution, DEFAULT_RESOLUTION); return 2; } } int retval = 0; wxString pdf_file; if ( parser.Found("output-diff", &pdf_file) ) { retval = doc_compare(doc1, doc2, pdf_file.utf8_str(), NULL) ? 0 : 1; } else if ( parser.Found("view") ) { wxGetApp().SetData(parser.GetParam(0), doc1, parser.GetParam(1), doc2); retval = wxEntry(argc, argv); } else { retval = doc_compare(doc1, doc2, NULL, NULL) ? 0 : 1; } g_object_unref(doc1); g_object_unref(doc2); // MinGW doesn't reliably flush streams on exit, so flush them explicitly: fflush(stdout); fflush(stderr); return retval; } 0707010000000D000081A4000003E800000064000000016039353E00000731000000000000000000000000000000000000001D00000000diff-pdf-0.5/gtk-zoom-in.xpm/* XPM */ static const char *gtk_zoom_in_xpm[] = { /* columns rows colors chars-per-pixel */ "24 24 70 1", " c #2D3436", ". c #2E3436", "X c #2E3536", "o c #2F3537", "O c #2F3538", "+ c #2F3638", "@ c #313537", "# c #303638", "$ c #363B3B", "% c #363B3D", "& c #353C3C", "* c #373D3F", "= c #383C3E", "- c #3B4142", "; c #3C4242", ": c #424544", "> c #4B4F4B", ", c #525350", "< c #555753", "1 c #585A56", "2 c #616564", "3 c #666B69", "4 c #666C69", "5 c #6D7171", "6 c #6F7373", "7 c #777B7A", "8 c #8F908D", "9 c #8F9290", "0 c #989C98", "q c #999E9A", "w c #ACAFAB", "e c #ACAEAC", "r c #B2B4B1", "t c #B8BBB5", "y c #BEC1BC", "u c #BEC0BD", "i c #D1D4CF", "p c #D2D6CF", "a c #CED0D0", "s c #CFD0D0", "d c #D1D2D1", "f c #D3D6D0", "g c #D4D6D2", "h c #D4D7D2", "j c #D5D6D3", "k c #D5D7D3", "l c #D5D9D1", "z c #D6DAD2", "x c #D9DCD5", "c c #DCDED8", "v c #DDDFD9", "b c #DDE0DA", "n c #DFE1DC", "m c #DFE2DC", "M c #E0E2DC", "N c #E2E4DF", "B c #E3E4E0", "V c #E5E7E3", "C c #E6E7E3", "Z c #E8E9E6", "A c #E9EAE6", "S c #E9EAE7", "D c #EAEAE7", "F c #EBECE9", "G c #ECECE9", "H c #ECECEA", "J c #ECEDEA", "K c #EDEDEB", "L c #EEEEEC", "P c None", /* pixels */ "PPPPPPPPPPPPPPPPPPPPPPPP", "PPPPPP @ .PPPPPPPPPPPP", "PPPPP 6eklt9%PPPPPPPPPPP", "PPP ;dHDCBMvd2 PPPPPPPPP", "PPP;GLHHGGDMxl4PPPPPPPPP", "PP sLLLL88LLBld=PPPPPPPP", "P 5GGLLL11LLGbxq PPPPPPP", "P wDLLLL<1LLLAby PPPPPPP", "P dZG81<<<<18Gmk@PPPPPPP", "P zBL81<<<118GBk PPPPPPP", "P tmDLLL<<GLLHBr PPPPPPP", "P 8bmLLL11LLLSS7 PPPPPPP", "PP=dxNLL88LLHHa@PPPPPPPP", "PPP2lxbDHGHDHH;PPPPPPPPP", "PPP 4dxcmBCZs;&PPPPPPPPP", "PPPPP&quhkr7+PP:+#PPPPPP", "PPPPPP + @ PPP#>&@PPPPP", "PPPPPPPPPPPPPPP#&,&@PPPP", "PPPPPPPPPPPPPPPP@&,$+PPP", "PPPPPPPPPPPPPPPPP+&,&#PP", "PPPPPPPPPPPPPPPPPP@&> PP", "PPPPPPPPPPPPPPPPPPP#@@PP", "PPPPPPPPPPPPPPPPPPPPPPPP", "PPPPPPPPPPPPPPPPPPPPPPPP" }; 0707010000000E000081A4000003E800000064000000016039353E00000732000000000000000000000000000000000000001E00000000diff-pdf-0.5/gtk-zoom-out.xpm/* XPM */ static const char *gtk_zoom_out_xpm[] = { /* columns rows colors chars-per-pixel */ "24 24 70 1", " c #2D3436", ". c #2E3436", "X c #2E3536", "o c #2F3537", "O c #2F3538", "+ c #2F3638", "@ c #313537", "# c #303638", "$ c #363B3B", "% c #363B3D", "& c #353C3C", "* c #373D3F", "= c #383C3E", "- c #3B4142", "; c #3C4242", ": c #424544", "> c #4B4F4B", ", c #525350", "< c #555753", "1 c #585A56", "2 c #616564", "3 c #666B69", "4 c #666C69", "5 c #6D7171", "6 c #6F7373", "7 c #777B7A", "8 c #8F908D", "9 c #8F9290", "0 c #989C98", "q c #999E9A", "w c #ACAFAB", "e c #ACAEAC", "r c #B2B4B1", "t c #B8BBB5", "y c #BEC1BC", "u c #BEC0BD", "i c #D1D4CF", "p c #D2D6CF", "a c #CED0D0", "s c #CFD0D0", "d c #D1D2D1", "f c #D3D6D0", "g c #D4D6D2", "h c #D4D7D2", "j c #D5D6D3", "k c #D5D7D3", "l c #D5D9D1", "z c #D6DAD2", "x c #D9DCD5", "c c #DCDED8", "v c #DDDFD9", "b c #DDE0DA", "n c #DFE1DC", "m c #DFE2DC", "M c #E0E2DC", "N c #E2E4DF", "B c #E3E4E0", "V c #E5E7E3", "C c #E6E7E3", "Z c #E8E9E6", "A c #E9EAE6", "S c #E9EAE7", "D c #EAEAE7", "F c #EBECE9", "G c #ECECE9", "H c #ECECEA", "J c #ECEDEA", "K c #EDEDEB", "L c #EEEEEC", "P c None", /* pixels */ "PPPPPPPPPPPPPPPPPPPPPPPP", "PPPPPP @ .PPPPPPPPPPPP", "PPPPP 6eklt9%PPPPPPPPPPP", "PPP ;dHDCBMvd2 PPPPPPPPP", "PPP;GLHHGGDMxl4PPPPPPPPP", "PP sLLLLLLLLBld=PPPPPPPP", "P 5GGLLLLLLLGbxq PPPPPPP", "P wDLLLLLLLLLAby PPPPPPP", "P dZG81<1<<18Gmk@PPPPPPP", "P zBL81<<<118GBk PPPPPPP", "P tmDLLLGLLLLHBr PPPPPPP", "P 8bmLLLLLLLLSS7 PPPPPPP", "PP=dxNLLLLLLHHa@PPPPPPPP", "PPP2lxbDHGHDHH;PPPPPPPPP", "PPP 4dxcmBCZs;&PPPPPPPPP", "PPPPP&quhkr7+PP:+#PPPPPP", "PPPPPP + @ PPP#>&@PPPPP", "PPPPPPPPPPPPPPP#&,&@PPPP", "PPPPPPPPPPPPPPPP@&,$+PPP", "PPPPPPPPPPPPPPPPP+&,&#PP", "PPPPPPPPPPPPPPPPPP@&> PP", "PPPPPPPPPPPPPPPPPPP#@@PP", "PPPPPPPPPPPPPPPPPPPPPPPP", "PPPPPPPPPPPPPPPPPPPPPPPP" }; 0707010000000F000081A4000003E800000064000000016039353E00000CB9000000000000000000000000000000000000001800000000diff-pdf-0.5/gutter.cpp/* * This file is part of diff-pdf. * * Copyright (C) 2009 TT-Solutions. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "gutter.h" #include <wx/dcclient.h> #include <wx/scrolwin.h> #include <wx/settings.h> #define EXTRA_ROOM_FOR_SCROLLBAR 20 Gutter::Gutter(wxWindow *parent, wxWindowID winid) : wxVListBox(parent, winid) { m_fontHeight = -1; SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); SetMinSize(wxSize(WIDTH + 2 * BORDER + EXTRA_ROOM_FOR_SCROLLBAR, -1)); } void Gutter::AddPage(const wxString& label, const wxImage& thumbnail) { m_labels.push_back(label); m_backgrounds.push_back(wxBitmap(thumbnail)); SetItemCount(m_backgrounds.size()); Refresh(); } void Gutter::SetThumbnail(int page, const wxImage& thumbnail) { m_backgrounds[page] = wxBitmap(thumbnail); Refresh(); } void Gutter::UpdateViewPos(wxScrolledWindow *win) { int sel = GetSelection(); if ( sel == wxNOT_FOUND ) return; int total_x, total_y; win->GetVirtualSize(&total_x, &total_y); float scale_x = float(m_backgrounds[sel].GetWidth()) / float(total_x); float scale_y = float(m_backgrounds[sel].GetHeight()) / float(total_y); win->GetViewStart(&m_viewPos.x, &m_viewPos.y); win->GetClientSize(&m_viewPos.width, &m_viewPos.height); m_viewPos.x = int(m_viewPos.x * scale_x); m_viewPos.y = int(m_viewPos.y * scale_y); m_viewPos.width = int(m_viewPos.width * scale_x); m_viewPos.height = int(m_viewPos.height * scale_y); Refresh(); } wxCoord Gutter::OnMeasureItem(size_t n) const { if ( m_fontHeight == -1 ) wxConstCast(this, Gutter)->m_fontHeight = GetCharHeight(); return m_backgrounds[n].GetHeight() + 3 * BORDER + m_fontHeight; } void Gutter::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const { const int xoffset = (GetClientSize().x - WIDTH) / 2; const int yoffset = BORDER; dc.DrawBitmap(m_backgrounds[n], rect.x + xoffset, rect.y + yoffset); const wxString label = m_labels[n]; int tw; dc.GetTextExtent(label, &tw, NULL); dc.SetFont(GetFont()); dc.DrawText ( label, rect.x + xoffset + (WIDTH - tw) / 2, rect.y + yoffset + m_backgrounds[n].GetHeight() + BORDER ); if ( GetSelection() == n ) { // draw current position if ( m_viewPos.IsEmpty() ) return; wxRect view(m_viewPos); view.Offset(rect.GetTopLeft()); view.Offset(wxPoint(xoffset, yoffset)); dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.SetPen(wxPen(*wxBLUE)); dc.DrawRectangle(view); } } 07070100000010000081A4000003E800000064000000016039353E000007AF000000000000000000000000000000000000001600000000diff-pdf-0.5/gutter.h/* * This file is part of diff-pdf. * * Copyright (C) 2009 TT-Solutions. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef _gutter_h_ #define _gutter_h_ #include <vector> #include <wx/image.h> #include <wx/bitmap.h> #include <wx/vlbox.h> class WXDLLIMPEXP_FWD_CORE wxScrolledWindow; // widget showing places of differences as well as scroll window's position class Gutter : public wxVListBox { public: // standard width of the gutter image in pixels static const int WIDTH = 100; // standard border static const int BORDER = 5; Gutter(wxWindow *parent, wxWindowID winid); // Add a new page to the gutter, with thumbnail's background to be shown void AddPage(const wxString& label, const wxImage& thumbnail); // Set the bitmap with thumbnail's background to be shown void SetThumbnail(int page, const wxImage& thumbnail); // Updates shown view position, i.e. the visible subset of scrolled window. // The gutter will indicate this area with a blue rectangle. void UpdateViewPos(wxScrolledWindow *win); protected: virtual wxCoord OnMeasureItem(size_t n) const; virtual void OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const; private: std::vector<wxString> m_labels; std::vector<wxBitmap> m_backgrounds; wxRect m_viewPos; int m_fontHeight; }; #endif // _gutter_h_ 07070100000011000041ED000003E800000064000000026039353E00000000000000000000000000000000000000000000001300000000diff-pdf-0.5/win3207070100000012000081ED000003E800000064000000016039353E0000027D000000000000000000000000000000000000002300000000diff-pdf-0.5/win32/collect-dlls.sh#!/bin/sh -e if [[ -z $1 || ! -f $2 ]]; then echo "Usage: $0 outputPath binary.exe" >&2 exit 1 fi OUTPUT=$1 EXE=$2 mkdir -p $OUTPUT rm -rf $OUTPUT/* cp -a $EXE $OUTPUT last_file_count=0 while true ; do file_count=`ls -1 $OUTPUT/* | wc -l` echo "count=$file_count" if [ $file_count -eq $last_file_count ] ; then break ; fi last_file_count=$file_count objdump -x $OUTPUT/* | grep "DLL Name" | cut -d: -f2 | sort | uniq | while read i ; do dll=`echo $i` # fixup weird line endings if [[ -f /mingw32/bin/$dll ]] ; then cp -anv /mingw32/bin/$dll $OUTPUT fi done done 07070100000013000081A4000003E800000064000000016039353E00001231000000000000000000000000000000000000001E00000000diff-pdf-0.5/win32/fonts.conf<?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> <fontconfig> <!-- ================================================================ Windows-specific configuration ================================================================ --> <dir>WINDOWSFONTDIR</dir> <cachedir>WINDOWSTEMPDIR_FONTCONFIG_CACHE</cachedir> <!-- ================================================================ fontconfig's 30-metric-aliases.conf (maps standard PostScript fonts to Windows ones) ================================================================ --> <!-- Alias similar/metric-compatible families from various sources: PostScript fonts: Helvetica Times Courier URW fonts: Nimbus Sans L Nimbus Roman No9 L Nimbus Mono L Microsoft fonts: Arial Times New Roman Courier New Liberation fonts: Liberation Sans Liberation Serif Liberation Mono StarOffice fonts: Albany Thorndale Cumberland AMT fonts: Albany AMT Thorndale AMT Cumberland AMT Of these, URW fonts are design compatible with PostScrict fonts, and the Liberation, StarOffice, and AMT ones are compatible with Microsoft fonts. We want for each of them to fallback to any of these available, but in an order preferring similar designs first. We do this in three steps: 1) Alias each specific to it's generic family. eg. Liberation Sans to Arial 2) Weak alias each generic to the other generic of its family. eg. Arial to Helvetica 3) Alias each generic to its specifics. eg. Arial to Liberation Sans, Albany, and Albany AMT --> <!-- Map specifics to generics --> <!-- PostScript --> <alias binding="same"> <family>Nimbus Sans L</family> <default> <family>Helvetica</family> </default> </alias> <alias binding="same"> <family>Nimbus Roman No9 L</family> <default> <family>Times</family> </default> </alias> <alias binding="same"> <family>Nimbus Mono L</family> <default> <family>Courier</family> </default> </alias> <!-- Microsoft --> <alias binding="same"> <family>Liberation Sans</family> <family>Albany</family> <family>Albany AMT</family> <default> <family>Arial</family> </default> </alias> <alias binding="same"> <family>Liberation Serif</family> <family>Thorndale</family> <family>Thorndale AMT</family> <default> <family>Times New Roman</family> </default> </alias> <alias binding="same"> <family>Liberation Mono</family> <family>Cumberland</family> <family>Cumberland AMT</family> <default> <family>Courier New</family> </default> </alias> <!-- Accept the other group as fallback --> <!-- PostScript --> <alias> <family>Helvetica</family> <default> <family>Arial</family> </default> </alias> <alias> <family>Times</family> <default> <family>Times New Roman</family> </default> </alias> <alias> <family>Courier</family> <default> <family>Courier New</family> </default> </alias> <!-- Microsoft --> <alias> <family>Arial</family> <default> <family>Helvetica</family> </default> </alias> <alias> <family>Times New Roman</family> <default> <family>Times</family> </default> </alias> <alias> <family>Courier New</family> <default> <family>Courier</family> </default> </alias> <!-- Map generics to specifics --> <!-- PostScript --> <alias binding="same"> <family>Helvetica</family> <accept> <family>Nimbus Sans L</family> </accept> </alias> <alias binding="same"> <family>Times</family> <accept> <family>Nimbus Roman No9 L</family> </accept> </alias> <alias binding="same"> <family>Courier</family> <accept> <family>Nimbus Mono L</family> </accept> </alias> <!-- Microsoft --> <alias binding="same"> <family>Arial</family> <accept> <family>Liberation Sans</family> <family>Albany</family> <family>Albany AMT</family> </accept> </alias> <alias binding="same"> <family>Times New Roman</family> <accept> <family>Liberation Serif</family> <family>Thorndale</family> <family>Thorndale AMT</family> </accept> </alias> <alias binding="same"> <family>Courier New</family> <accept> <family>Liberation Mono</family> <family>Cumberland</family> <family>Cumberland AMT</family> </accept> </alias> </fontconfig> 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!245 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor