diff --git a/COPYING b/COPYING new file mode 100644 index 000000000..6cbbd9c01 --- /dev/null +++ b/COPYING @@ -0,0 +1,35 @@ +This version of Gnofract 4D is distributed under the BSD License. + +Note that earlier versions (versions 1.0 to 1.9 inclusive) were +distributed under the GNU GPL. + +Copyright (c) 1999-2006, Tim Whidbey +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * 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. + + * Neither the name of Tim Whidbey nor the names of any other +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT +OWNER 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. diff --git a/benchfct.py b/benchfct.py new file mode 100755 index 000000000..1eaae24a1 --- /dev/null +++ b/benchfct.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +import sys +import os +from time import time as now + +class Benchmark: + def __init__(self, command, args): + self.last_time = None + self.pos = 0 + self.args = args + self.command = command + + def build(self): + cmd = self.command + " --buildonly foo.so " + self.args + print cmd + result = os.system(cmd) + assert result == 0 + + def run(self): + last_time = now() + result = os.system(self.command + " --usebuilt ./foo.so " + self.args) + assert result == 0 + new_time = now() + return new_time - last_time + +repeats = 1 +command = "./gnofract4d -i 2560 -j 2048 --nogui " +args = "" +for arg in sys.argv[1:]: + if arg == "--repeat": + repeats = 5 + else: + args += " " + arg + +bench = Benchmark(command, args) +bench.build() +times = [] +for i in xrange(repeats): + t = bench.run() + print t + times.append(t) + +print "stats" +print "min:(%.4f), max(%.4f), average(%.4f)" % (min(times), max(times), sum(times)/len(times)) + + + + diff --git a/benchmark.py b/benchmark.py new file mode 100755 index 000000000..0147efbda --- /dev/null +++ b/benchmark.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +import sys +import os +import getopt +import operator +from time import time as now + +# gettext +import gettext +os.environ.setdefault('LANG', 'en') +if os.path.isdir('po'): + gettext.install('gnofract4d','po') +else: + gettext.install('gnofract4d') + +import gtk + +from fract4d import fractmain, image +from fract4dgui import main_window + +files = [ + 'testdata/std.fct', + 'testdata/param.fct', + 'testdata/valley_test.fct', + 'testdata/trigcentric.fct', + 'testdata/zpower.fct' + ] + +class Benchmark: + def __init__(self, useGui): + self.last_time = None + self.pos = 0 + self.useGui = useGui + self.w = 320 + self.h = 240 + + def run_gui(self): + + window = main_window.MainWindow() + + window.f.set_size(self.w,self.h) + window.f.thaw() + + times = [] + self.last_time = now() + + def status_changed(f,status): + if status == 0: + # done + new_time = now() + times.append(new_time - self.last_time) + self.last_time = new_time + self.pos += 1 + if self.pos < len(files): + window.load(files[self.pos]) + else: + gtk.main_quit() + + window.f.connect('status-changed', status_changed) + window.load(files[0]) + gtk.main() + return times + + def run_nogui(self): + main = fractmain.T() + print main.compiler.path_lists + times = [] + last_time = now() + for file in files: + main.load(file) + im = image.T(self.w,self.h) + main.draw(im) + im.save(file + ".png") + new_time = now() + times.append(new_time - last_time) + + return times + + def run(self): + if self.useGui: + times = self.run_gui() + else: + times = self.run_nogui() + + for (file,time) in zip(files,times): + print "%.4f %s" % (time,file) + + print reduce(operator.__add__,times,0) + +useGui = True +repeats = 1 +for arg in sys.argv[1:]: + if arg == "--nogui": + useGui = False + if arg == "--repeat": + repeats = 3 + +for i in xrange(repeats): + bench = Benchmark(useGui) + bench.run() + + + diff --git a/buildtools/__init__.py b/buildtools/__init__.py new file mode 100644 index 000000000..cf529d79a --- /dev/null +++ b/buildtools/__init__.py @@ -0,0 +1,2 @@ +#!/usr/bin/env python + diff --git a/buildtools/my_bdist_rpm.py b/buildtools/my_bdist_rpm.py new file mode 100644 index 000000000..78ec652a7 --- /dev/null +++ b/buildtools/my_bdist_rpm.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python + +# Override the default bdist_rpm distutils command to do what I want + +import re +import glob +import os +import sys + +from distutils.command.bdist_rpm import bdist_rpm +from distutils.core import Command + +topdir_re = re.compile(r'.*topdir (.*)') + +class my_bdist_rpm (bdist_rpm): + user_options = bdist_rpm.user_options + def __init__(self, dict): + bdist_rpm.__init__(self,dict) + + def insert_after(self,spec, find,add): + for i in xrange(len(spec)): + if spec[i].startswith(find): + spec.insert(i,add) + return + + def replace(self,spec,find, new): + for i in xrange(len(spec)): + if spec[i].startswith(find): + print "replacing %s with %s" % (spec[i], new) + spec[i] = new + return + + def add_to_section(self,spec,sect,add): + found = False + for i in xrange(len(spec)): + if spec[i].startswith(sect): + found = True + elif spec[i].startswith('%'): + if found: + spec.insert(i,add) + return + if found: + # this is the last section + spec.insert(i,add) + else: + raise IndexError("sect %s not found" % sect) + + def spawn(self,cmd): + '''HACK: On FC4 rpmbuild creates 2 RPMS, the normal one and a + debuginfo one. This horrifies the bdist_rpm which comes with pythons + older than 2.4 - these only expect 1 RPM. This works around + that by deleting the extraneous debuginfo RPM. Overriding this + method rather than run() because there's less code. ''' + bdist_rpm.spawn(self,cmd) + v = sys.version_info[0] * 10 + sys.version_info[1] + if v < 24 and cmd[0] == "rpmbuild": + for arg in cmd: + m = topdir_re.match(arg) + if m: + print "doing 2.3-cleanup" + dir = m.group(1) + debuginfo_glob = os.path.join( + dir,"RPMS", "*", "*debuginfo*") + rpms = glob.glob(debuginfo_glob) + print "found extraneous rpms", rpms + for rpm in rpms: + os.remove(rpm) + + + def _make_spec_file(self): + '''HACK: override the default PRIVATE function to specify: + AutoReqProv: no + add some commands to update mime types + ''' + + spec = bdist_rpm._make_spec_file(self) + + # reduce the number of explicit pre-requisites + self.insert_after(spec, 'Url','AutoReqProv: no') + + # remove an old tag that newer rpmbuilds dislike + self.replace(spec, 'Copyright', 'License: BSD') + + # install a .desktop file and register .fct files with ourselves + self.insert_after(spec, '%define', '%define desktop_vendor ey') + self.add_to_section(spec, '%install', ''' +%post +update-mime-database %{_datadir}/mime &> /dev/null || : +update-desktop-database &> /dev/null || : + +%postun +update-mime-database %{_datadir}/mime &> /dev/null || : +update-desktop-database &> /dev/null || : + +''') + + print "SPEC>" + print "\n".join(spec) + print "EOF>" + + return spec diff --git a/buildtools/my_build.py b/buildtools/my_build.py new file mode 100644 index 000000000..836b91b36 --- /dev/null +++ b/buildtools/my_build.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +# Override the default build distutils command to do what I want + +from distutils.command.build import build +from distutils.core import Command + +class my_build (build): + user_options = build.user_options + def __init__(self, dict): + build.__init__(self,dict) + + new_commands = [] + for (name,pred) in build.sub_commands: + if name == "build_ext": + name = "my_build_ext" + new_commands.append((name,pred)) + + build.sub_commands = new_commands + diff --git a/buildtools/my_build_ext.py b/buildtools/my_build_ext.py new file mode 100644 index 000000000..a1d60afd1 --- /dev/null +++ b/buildtools/my_build_ext.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +# Override the default build distutils command to do what I want + +from distutils.command.build_ext import build_ext +from distutils.core import Command +import os +import re + +remove_mtune = re.compile(r'-mtune=\w*') + +class my_build_ext (build_ext): + user_options = build_ext.user_options + def __init__(self, dict): + build_ext.__init__(self,dict) + self._build_temp = None + + def build_extensions(self): + # python2.2 doesn't honor these, so we have to sneak them in + cxx = os.environ.get("CXX") + cc = os.environ.get("CC") + + print "compiling with", cc + if cc: + self.compiler.preprocessor[0] = cc + self.compiler.compiler_so[0] = cc + self.compiler.compiler[0] = cc + + if cc.find("33") > -1: + print "cc is old" + # rpm thinks we should have -mtune, but older gcc doesn't like it + cflags = os.environ.get("CFLAGS") + if cflags != None: + cflags = remove_mtune.sub("",cflags) + print "cflags", cflags + os.environ["CFLAGS"] = cflags + + self.compiler.compiler = [ + opt for opt in self.compiler.compiler \ + if opt.find("-mtune") == -1 ] + + self.compiler.compiler_so = [ + opt for opt in self.compiler.compiler_so \ + if opt.find("-mtune") == -1 ] + + if cxx: + if hasattr(self.compiler, "compiler_cxx"): + self.compiler.compiler_cxx[0] = cxx + self.compiler.linker_so[0] = cxx + + build_ext.build_extensions(self) + diff --git a/buildtools/my_install_lib.py b/buildtools/my_install_lib.py new file mode 100644 index 000000000..612863030 --- /dev/null +++ b/buildtools/my_install_lib.py @@ -0,0 +1,24 @@ +# I need to be able to install an executable script to a data directory +# so scripts= is no use. Pretend it's data then fix up the permissions +# with chmod afterwards + +import os +import stat + +from distutils.command.install_lib import install_lib + +class my_install_lib(install_lib): + def install(self): + #need to change self.install_dir to the library dir + outfiles = install_lib.install(self) + for f in outfiles: + if f.endswith("get.py"): + if os.name == 'posix': + # Set the executable bits (owner, group, and world) on + # the script we just installed. + mode = ((os.stat(f)[stat.ST_MODE]) | 0555) & 07777 + print "changing mode of %s to %o" % (f, mode) + os.chmod(f, mode) + + return outfiles + diff --git a/createdocs.py b/createdocs.py new file mode 100755 index 000000000..e154e6fbb --- /dev/null +++ b/createdocs.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python + +# run this to update some tables in the documentation + +# making this a separate cmd (not part of setup.py) because importing +# gtk was causing "setup.py build" to crash - inexplicable... + +# also the other python versions don't have gtk as a module, +# so were reporting errors. + +import sys +import os + +def create_stdlib_docs(): + 'Autogenerate docs' + try: + # create list of stdlib functions + from fract4d import createdocs as cd1 + cd1.main("doc/gnofract4d-manual/C/stdlib.xml") + + # create list of mouse and GUI commands + import fract4dgui.createdocs + fract4dgui.createdocs.main("doc/gnofract4d-manual/C/commands.xml") + + # create HTML version of docs for them as don't have yelp + os.chdir("doc/gnofract4d-manual/C") + os.system("xsltproc --output gnofract4d-manual.html --stringparam html.stylesheet docbook.css gnofract4d.xsl gnofract4d-manual.xml") + except Exception, err: + print >>sys.stderr,\ + "Problem creating docs. Online help will be incomplete." + print >>sys.stderr, err + +create_stdlib_docs() diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 000000000..bc3b61ebe --- /dev/null +++ b/debian/changelog @@ -0,0 +1,59 @@ +gnofract4d (3.13-1ubuntu1) gutsy; urgency=low + + * New version of program + + -- Tim Whidbey Sun, 17 May 2009 14:23:00 +0800 + +gnofract4d (3.12-1ubuntu1) gutsy; urgency=low + + * New version of program + + -- Tim Whidbey Sun, 17 May 2009 14:23:00 +0800 + +gnofract4d (3.11-1ubuntu1) gutsy; urgency=low + + * New version of program + + -- Tim Whidbey Sat, 19 Jan 2008 14:23:00 +0800 + +gnofract4d (3.10-1ubuntu1) gutsy; urgency=low + + * New version of program + + -- Tim Whidbey Sat, 19 Jan 2008 14:23:00 +0800 + +gnofract4d (3.9-1ubuntu1) gutsy; urgency=low + + * New version of program + + -- Tim Whidbey Sat, 19 Jan 2008 14:23:00 +0800 + +gnofract4d (3.8-1ubuntu1) gutsy; urgency=low + + * New version of program + + -- Tim Whidbey Sat, 19 Jan 2008 14:23:00 +0800 + +gnofract4d (3.7-1ubuntu1) gutsy; urgency=low + + * Pulled Debian files into upstream repository + * Based on version by Aleksander Adamowski on REVU + + -- Tim Whidbey Sat, 10 Nov 2007 13:45:00 +0800 + +gnofract4d (3.4-1ubuntu1) feisty; urgency=low + + * Initial Ubuntu release (edits made per suggestion of REVU committee) + * Based on initial Ubuntu packages by and cleaned + up + * Added missing man page + + -- Aleksander Adamowski Fri, 20 Jul 2007 15:31:12 +0200 + +gnofract4d (3.4-1) unstable; urgency=low + + * Initial release (Closes: #420507) + + -- Francesco Namuri Sun, 22 Apr 2007 17:56:44 +0200 + + diff --git a/debian/compat b/debian/compat new file mode 100644 index 000000000..7ed6ff82d --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 000000000..0dff8f937 --- /dev/null +++ b/debian/control @@ -0,0 +1,22 @@ +Source: gnofract4d +Section: graphics +Version: 3.11-1ubuntu1 +Priority: extra +Maintainer: Tim Whidbey +XSBC-Original-Maintainer: Francesco Namuri +Build-Depends: debhelper (>= 5), cdbs, python, python-dev, python-support (>= 0.5.3), libpng12-dev, libgconf2-dev, libjpeg62-dev +Standards-Version: 3.7.2 +XS-Python-Version: current + +Package: gnofract4d +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}, libc6-dev +XB-Python-Version: ${python:Versions} +Description: a fractal images creator + Gnofract 4D is a program which allows anyone to create beautiful images + called fractals. The images are automatically created by the computer + based on mathematical principles. These include the Mandelbrot and + Julia sets and many more. You don't need to do any math: you can + explore a universe of images just using a mouse. + . + Project Homepage: http://gnofract4d.sourceforge.net/ diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 000000000..dbbfc45b9 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,100 @@ +This package was debianized by Francesco Namuri on +Sun, 22 Apr 2007 17:56:44 +0200. + +It was downloaded from http://gnofract4d.sourceforge.net/download.html + +Upstream Author: Tim Whidbey + +Copyrights: + (c) 1999-2007, Tim Whidbey. + + fract4gui/FCTGen.py, + fract4gui/DlgAdvOpt.py, + fract4d/animation.py: (c) 2006, Branko Kokanovic + + fract4d/yacc.py, + fract4d/lex.py: (c) 2001, David M. Beazley + + part of formulas/gf4d.frm, + formulas/fractint-g4.frm: (c) 1998-1999, Morgan L. Owens + + formulas/fractint-g4.frm: + (c) 1998-1999, Morgan L. Owens, + Mark Peterson, + (c) 1993, Don Archer, + (c) 1993, Ron Barnett, + Bradley Beacham, + Pieter Branderhorst, + JM Collard-Richard, + W. Leroy Davis, + Rob Den Braasem, + Chuck Ebbert, + John Horner, + Sylvie Gallet, + Chris Green, + Richard Hughes, + Gordon Lamb, + Kevin Lee, + Ron Lewen, + Lee Skinner, + Scott Taylor, + Michael Theroux, + Timothy Wegner. + +License: + The sources of Gnofract are distributed under the BSD License: + " + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * 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. + + * Neither the name of Tim Whidbey nor the names of any other + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT + OWNER 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. + " + + fract4d/yacc.py, fract4d/lex.pyi,fract4dgui/FCTGen.py are under LGPL: + " + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., + " + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + See the file /usr/share/common-licenses/LGPL for a complete copy of the LGPL. + +The Debian packaging is (C) 2007, Francesco Namuri and +is licensed under the GPL, see `/usr/share/common-licenses/GPL'. + +The Ubuntu package release is (c) 2007, Follower of the Clawed Albino +and is licensed under the GPL, see `/usr/share/common-licenses/GPL'. diff --git a/debian/docs b/debian/docs new file mode 100644 index 000000000..381f17570 --- /dev/null +++ b/debian/docs @@ -0,0 +1,2 @@ +README +PKG-INFO diff --git a/debian/files b/debian/files new file mode 100644 index 000000000..863c11481 --- /dev/null +++ b/debian/files @@ -0,0 +1 @@ +gnofract4d_3.11-1ubuntu1_amd64.deb graphics extra diff --git a/debian/lintian/overrides/CVS/Entries b/debian/lintian/overrides/CVS/Entries new file mode 100644 index 000000000..838e9a018 --- /dev/null +++ b/debian/lintian/overrides/CVS/Entries @@ -0,0 +1,2 @@ +/gnofract4d/1.1/Sat Nov 10 22:32:09 2007// +D diff --git a/debian/lintian/overrides/CVS/Repository b/debian/lintian/overrides/CVS/Repository new file mode 100644 index 000000000..5db4a50da --- /dev/null +++ b/debian/lintian/overrides/CVS/Repository @@ -0,0 +1 @@ +gnofract4d/debian/lintian/overrides diff --git a/debian/lintian/overrides/CVS/Root b/debian/lintian/overrides/CVS/Root new file mode 100644 index 000000000..acd25a096 --- /dev/null +++ b/debian/lintian/overrides/CVS/Root @@ -0,0 +1 @@ +:ext:catenary@gnofract4d.cvs.sourceforge.net:/cvsroot/gnofract4d diff --git a/debian/lintian/overrides/gnofract4d b/debian/lintian/overrides/gnofract4d new file mode 100644 index 000000000..3c80c2f0b --- /dev/null +++ b/debian/lintian/overrides/gnofract4d @@ -0,0 +1,2 @@ +# Python modules and scripts need not be executable: +gnofract4d binary: script-not-executable \ No newline at end of file diff --git a/debian/menu b/debian/menu new file mode 100644 index 000000000..cf3632483 --- /dev/null +++ b/debian/menu @@ -0,0 +1,3 @@ +?package(gnofract4d):needs="X11" section="Apps/Graphics"\ + icon="gnofract4d-logo.xpm" title="Gnofract 4D"\ + longtitle="A fractal images creator" command="/usr/bin/gnofract4d" diff --git a/debian/pycompat b/debian/pycompat new file mode 100644 index 000000000..0cfbf0888 --- /dev/null +++ b/debian/pycompat @@ -0,0 +1 @@ +2 diff --git a/debian/pyversions b/debian/pyversions new file mode 100644 index 000000000..8b253bc3c --- /dev/null +++ b/debian/pyversions @@ -0,0 +1 @@ +2.4- diff --git a/debian/rules b/debian/rules new file mode 100755 index 000000000..10cb76fe2 --- /dev/null +++ b/debian/rules @@ -0,0 +1,12 @@ +#!/usr/bin/make -f + +DEB_PYTHON_SYSTEM = pysupport +include /usr/share/cdbs/1/rules/debhelper.mk +include /usr/share/cdbs/1/class/python-distutils.mk +include /usr/share/cdbs/1/rules/simple-patchsys.mk + +clean:: + dh_testdir + dh_testroot + dh_clean fract4d/fract4d_stdlib.so fract4d/fract4dc.so + dh_clean fract4dgui/fract4dguic.so diff --git a/debian/stamp-patched b/debian/stamp-patched new file mode 100644 index 000000000..e69de29bb diff --git a/debian/watch b/debian/watch new file mode 100644 index 000000000..7e85de04f --- /dev/null +++ b/debian/watch @@ -0,0 +1,4 @@ +# Compulsory line, this is a version 3 file +version=3 + +http://sf.net/gnofract4d/gnofract4d-(.*)\.tar\.gz diff --git a/mkstatic.py b/mkstatic.py new file mode 100644 index 000000000..d74a46eb5 --- /dev/null +++ b/mkstatic.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +# gettext +import gettext +os.environ.setdefault('LANG', 'en') +if os.path.isdir('po'): + gettext.install('gnofract4d','po') +else: + gettext.install('gnofract4d') + +# nogui modules +from fract4d import fractal, fractmain, options + +def main(args): + opts = options.T() + try: + opts.parse(args) + except options.OptionError, err: + print get_version_info() + print opts.help() + + print "Error parsing arguments: %s" % err + return 1 + + t = fractmain.T() + diff --git a/setup.py b/setup.py new file mode 100755 index 000000000..4cfe2af52 --- /dev/null +++ b/setup.py @@ -0,0 +1,287 @@ +#!/usr/bin/env python + +import shutil +from distutils.core import setup, Extension +import distutils.sysconfig +import os +import stat +import commands +import sys + +gnofract4d_version = '3.13' + +if float(sys.version[:3]) < 2.4: + print "Sorry, you need Python 2.4 or higher to run Gnofract 4D." + print "You have version %s. Please upgrade." % sys.version + sys.exit(1) + +# hack to use a different Python for building if an env var is set +# I use this to build python-2.2 and 2.4 RPMs. +build_version = os.environ.get("BUILD_PYTHON_VERSION") +build_python = os.environ.get("BUILD_PYTHON") + +if build_version and build_python and sys.version[:3] != build_version: + print sys.version[:3], build_version + args = ["/usr/bin/python"] + sys.argv + print "running other Python version %s with args: %s" % (build_python,args) + os.execv(build_python, args) + +from buildtools import my_bdist_rpm, my_build, my_build_ext, my_install_lib + +# Extensions need to link against appropriate libs +# We use pkg-config to find the appropriate set of includes and libs + +def call_package_config(package,option,optional=False): + '''invoke pkg-config, if it exists, to find the appropriate + arguments for a library''' + cmd = "pkg-config %s %s" % (package, option) + (status,output) = commands.getstatusoutput(cmd) + if status != 0: + if optional: + print >>sys.stderr, "Can't find '%s'" % package + print >>sys.stderr, "Some functionality will be disabled" + return [] + else: + print >>sys.stderr, "Can't set up. Error running '%s'." % cmd + print >>sys.stderr, output + print >>sys.stderr, "Possibly you don't have one of these installed: '%s'." % package + sys.exit(1) + + return output.split() + +extra_macros = [] + +png_flags = call_package_config("libpng", "--cflags", True) +if png_flags != []: + extra_macros.append(('PNG_ENABLED', 1)) +else: + print "NO PNG HEADERS FOUND" + +png_libs = call_package_config("libpng", "--libs", True) + +jpg_lib = "jpeg" +if os.path.isfile("/usr/include/jpeglib.h"): + extra_macros.append(('JPG_ENABLED', 1)) + jpg_libs = [ jpg_lib ] +else: + print "NO JPEG HEADERS FOUND" + jpg_libs = [] + +#not ready yet. +have_gmp = False # os.path.isfile("/usr/include/gmp.h") + +# use currently specified compilers, not ones from when Python was compiled +# this is necessary for cross-compilation +compiler = os.environ.get("CC","gcc") +cxxcompiler = os.environ.get("CXX","g++") + +fract4d_sources = [ + 'fract4d/c/fract4dmodule.cpp', + 'fract4d/c/cmap.cpp', + 'fract4d/c/pointFunc.cpp', + 'fract4d/c/fractFunc.cpp', + 'fract4d/c/STFractWorker.cpp', + 'fract4d/c/MTFractWorker.cpp', + 'fract4d/c/image.cpp', + 'fract4d/c/imageIO.cpp', + 'fract4d/c/fract_stdlib.cpp' + ] + +# this is a hack to build 2 versions of the same extension. +# we want to create a standard fract4dc which doesn't depend on gmp +# and a second fract4dcgmp which does. These are both built from the +# same source files but in the latter case with USE_GMP defined +# This is so I can ship a single binary for gnofract4d which supports +# both users with GMP and users without it, by conditionally loading +# the appropriate extension +fract4d_gmp_sources = [] +if(have_gmp): + for sourcefile in fract4d_sources: + # this particular part of the hack is so that each file gets + # compiled twice + gmp_sourcefile = sourcefile.replace(".cpp","_gmp.cpp") + os.system("cp %s %s" % (sourcefile, gmp_sourcefile)) + fract4d_gmp_sources.append(gmp_sourcefile) + +module_gmp = Extension( + 'fract4d.gmpy', + sources = [ + 'fract4d/gmpy/gmpy.c' + ], + libraries = ['gmp'] + ) + +defines = [ ('_REENTRANT',1), + ('THREADS',1), + #('STATIC_CALC',1), + #('NO_CALC', 1), # set this to not calculate the fractal + #('DEBUG_CREATION',1), # debug spew for allocation of objects + #('DEBUG_ALLOCATION',1), # debug spew for array handling + ] + +module_fract4dgmp = Extension( + 'fract4d.fract4dcgmp', + sources = fract4d_gmp_sources, + include_dirs = [ + 'fract4d/c' + ], + libraries = [ + 'stdc++', 'gmp' + ] + jpg_libs, + extra_compile_args = [ + '-Wall', '-Wno-strict-prototypes' + ] + png_flags, + extra_link_args = png_libs, + define_macros = defines + [('USE_GMP',1)] + extra_macros, + undef_macros = [ 'NDEBUG'] + ) + +if "win" in sys.platform: + warnings = '/W3' + libs = [ 'pthreadVC2', 'libdl' ] + osdep = [ '/DWIN32', '/DWINDOWS', '/D_USE_MATH_DEFINES', '/D_CRT_SECURE_NO_WARNINGS', '/EHsc', '/Ox' ] + osdep += [ '/I"F:/Gamma/GTK+/Win32/include/glib-2.0/"', '/I"F:/Gamma/GTK+/Win32/lib/glib-2.0/include/"' ] + extra_source = [ 'fract4d/c/win32func.cpp', 'fract4d/c/fract4d_stdlib_exports.cpp' ] + extra_link = [ '/LIBPATH:"F:/Gamma/GTK+/Win32/lib"' ] +else: + warnings = '-Wall' + libs = [ 'stdc++' ] + osdep = [] + extra_source = [] + extra_link = [] + +fract4d_sources += extra_source + +module_fract4dc = Extension( + 'fract4d.fract4dc', + sources = fract4d_sources, + include_dirs = [ + 'fract4d/c' + ], + libraries = libs + jpg_libs, + #library_dirs=['/home/edwin/gnofract4d'], + extra_compile_args = [ + warnings, + ] + osdep + png_flags, + extra_link_args = extra_link + png_libs, + define_macros = defines + extra_macros, + #undef_macros = [ 'NDEBUG'], + ) + +module_cmap = Extension( + 'fract4d.fract4d_stdlib', + sources = [ + 'fract4d/c/cmap.cpp', + 'fract4d/c/image.cpp', + 'fract4d/c/fract_stdlib.cpp' + ] + extra_source, + include_dirs = [ + 'fract4d/c' + ], + libraries = libs, + extra_link_args = extra_link, + define_macros = [ ('_REENTRANT', 1)] + ) + +modules = [module_fract4dc, module_cmap] +if have_gmp: + modules.append(module_fract4dgmp) + modules.append(module_gmp) + +def get_files(dir,ext): + return [ os.path.join(dir,x) for x in os.listdir(dir) if x.endswith(ext)] + +setup (name = 'gnofract4d', + version = gnofract4d_version, + description = 'A program to draw fractals', + long_description = \ +'''Gnofract 4D is a fractal browser. It can generate many different fractals, +including some which are hybrids between the Mandelbrot and Julia sets, +and includes a Fractint-compatible parser for your own fractal formulas.''', + author = 'Tim Whidbey', + author_email = 'catenary@users.sourceforge.net', + maintainer = 'Tim whidbey', + maintainer_email = 'catenary@users.sourceforge.net', + keywords = "fractal Mandelbrot Julia fractint chaos", + url = 'http://gnofract4d.sourceforge.net/', + packages = ['fract4d', 'fract4dgui', 'fractutils'], + package_data = { 'fract4dgui' : [ 'ui.xml'] }, + ext_modules = modules, + scripts = ['gnofract4d'], + data_files = [ + # color maps + ('share/gnofract4d/maps', + get_files("maps",".map") + + get_files("maps",".cs") + + get_files("maps", ".ugr")), + + # formulas + ('share/gnofract4d/formulas', + get_files("formulas","frm") + + get_files("formulas", "ucl") + + get_files("formulas", "uxf")), + + # documentation + ('share/gnome/help/gnofract4d/C', + get_files("doc/gnofract4d-manual/C", "xml")), + ('share/gnome/help/gnofract4d/C/figures', + get_files("doc/gnofract4d-manual/C/figures",".png")), + ('share/gnome/help/gnofract4d/C', + get_files("doc/gnofract4d-manual/C", "html")), + ('share/gnome/help/gnofract4d/C', + get_files("doc/gnofract4d-manual/C",".css")), + + #internal pixmaps + ('share/pixmaps/gnofract4d', + ['pixmaps/improve_now.png', + 'pixmaps/explorer_mode.png']), + + # icon + ('share/pixmaps', + ['pixmaps/gnofract4d-logo.png']), + + # .desktop file + ('share/applications', ['gnofract4d.desktop']), + + # MIME type registration + ('share/mime/packages', ['gnofract4d-mime.xml']), + + # doc files + ('share/doc/gnofract4d/', + ['COPYING', 'README']), + ], + cmdclass={ + "my_bdist_rpm": my_bdist_rpm.my_bdist_rpm, + "build" : my_build.my_build, + "my_build_ext" : my_build_ext.my_build_ext, + "install_lib" : my_install_lib.my_install_lib + } + ) + +# I need to find the file I just built and copy it up out of the build +# location so it's possible to run without installing. Can't find a good +# way to extract the actual target directory out of distutils, hence +# this egregious hack + +so_extension = distutils.sysconfig.get_config_var("SO") + +lib_targets = { + "fract4dc" + so_extension : "fract4d", + "fract4d_stdlib" + so_extension : "fract4d", + "fract4dcgmp" + so_extension : "fract4d", + "gmpy" + so_extension: "fract4d" + } +if 'win' in sys.platform: + lib_targets["fract4d_stdlib.lib"] = "fract4d" + +def copy_libs(dummy,dirpath,namelist): + for name in namelist: + target = lib_targets.get(name) + if target != None: + name = os.path.join(dirpath, name) + shutil.copy(name, target) + +os.path.walk("build",copy_libs,None) +if 'win' in sys.platform: + shutil.copy("fract4d/fract4d_stdlib.pyd", "fract4d_stdlib.pyd") + diff --git a/test.py b/test.py new file mode 100755 index 000000000..3cf058867 --- /dev/null +++ b/test.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python + +# run all the tests +import os +import sys +import unittest +import re +import getopt + +from fract4d import options + +try: + # a hack, but seems easy enough + os.system("cp gnofract4d gnofract4d.py") + import gnofract4d +finally: + os.remove("gnofract4d.py") + +print "Running all unit tests. This may take several minutes." + +class Test(unittest.TestCase): + def testSetupPyVersionMatches(self): + doc = open("setup.py").read() + doc_re = re.compile(r"gnofract4d_version = '(\S+)'") + m = doc_re.search(doc) + + self.failUnless(m,"setup.py doesn't specify version") + self.assertEqual(options.version, m.group(1)) + + def testDocVersionMatches(self): + # check the docs + doc = open("doc/gnofract4d-manual/C/gnofract4d-manual.xml").read() + doc_re = re.compile(r'\<\!ENTITY version "(\S+)"\>') + + m = doc_re.search(doc) + self.failUnless(m,"doc doesn't specify version") + self.assertEqual(options.version,m.group(1), "Version mismatch") + + def testWebsiteVersionMatches(self): + if not os.path.exists("website"): + # not included in source dist + return + mkweb = open("website/mkweb.py").read() + ver_re = re.compile(r'text="Version (\S+) released.') + + m = ver_re.search(mkweb) + self.failUnless(m,"doc doesn't specify version") + self.assertEqual(options.version,m.group(1), "Version mismatch") + + def testPkgInfoVersionMatches(self): + pki = open("PKG-INFO").read() + pk_re = re.compile(r'^Version: (\S+)', re.MULTILINE) + m = pk_re.search(pki) + self.failUnless(m,"PKG-INFO doesn't specify version") + self.assertEqual(options.version, m.group(1), "Version mismatch") + + def testChangeLogVersionMatches(self): + changelog_top = open("debian/changelog").readline() + cl_re = re.compile(r'gnofract4d \(([0-9\.]+)-1ubuntu1\)') + m = cl_re.search(changelog_top) + self.failUnless(m,"changelog doesn't specify version") + self.assertEqual(options.version, m.group(1), "Version mismatch") + + def testGenerateMandelbrot(self): + if os.path.exists("test.png"): + os.remove("test.png") + try: + gnofract4d.main(["-s", "test.png", "--width", "24", "-j", "12", "-q"]) + self.failUnless(os.path.exists("test.png")) + finally: + if os.path.exists("test.png"): + os.remove("test.png") + + + def testVersionChecks(self): + self.assertEqual(False, gnofract4d.test_version(2,6,0)) + self.assertEqual(True, gnofract4d.test_version(2,12,0)) + self.assertEqual(True, gnofract4d.test_version(3,0,0)) + + self.assertEqual(False, gnofract4d.test_version(1,99,0)) + self.assertEqual(False, gnofract4d.test_version(2,0,0)) + self.assertEqual(False, gnofract4d.test_version(2,11,0)) + +def suite(): + return unittest.makeSuite(Test,'test') + +def main(): + os.chdir('fract4d') + os.system('./test.py') + os.chdir('../fract4dgui') + os.system('./test.py') + os.chdir('../fractutils') + os.system('./test.py') + os.chdir('..') + + unittest.main(defaultTest='suite') + + +if __name__ == '__main__': + if len(sys.argv) > 1 and sys.argv[1] == "--thisonly": + sys.argv.remove("--thisonly") + unittest.main(defaultTest='suite') + else: + main() + diff --git a/test_regress.py b/test_regress.py new file mode 100755 index 000000000..b44f7dc43 --- /dev/null +++ b/test_regress.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python + +# compare output of fract4d with saved 'known good' files +# complain about anything different + +# this requires the Python Imaging Library to run. + +import os +import operator +from PIL import Image, ImageChops, ImageFilter, ImageStat + +good_files = [ + # look ok + "abyssal.fct", + "antialias_bug.fct", + "bailout_breaker.fct", + #"barnsley_t2_odd.fct", + "barnsley_worm.fct", + "cathedral.fct", + "chaos_engine.fct", + "compass_rose.fct", + "crest.fct", + "cubicspiral.fct", + "towers.fct", + "valley_of_obvious_errors.fct", + "shattered.fct", + +] + +bad_files = [ + # not equivalent + "caduceus.fct", + "caduceus_fixed.fct", + "contrail.fct", + "daisychain.fct", +] + +def render(outfile, fctfile): + cmd = "./gnofract4d --nogui --threads 4 -i 64 -j 48 -s %s -q %s" % (outfile,fctfile) + #print cmd + ret = os.system(cmd) + if ret != 0: + raise Exception("error generating image") + +def compare(fctfile): + outbase = os.path.basename(fctfile) + ".png" + outfile = "testdata/new_output/" + outbase + render(outfile, fctfile) + new_image = Image.open(outfile) + old_image = Image.open("testdata/saved_output/" + outbase) + + diff = ImageChops.difference(new_image,old_image) + + diff_file = "testdata/diffs/" + outbase + diff.save(diff_file) + + stats = ImageStat.Stat(diff) + print "%f\t%d\t%f" % \ + (total(stats.mean), total(stats.median), total(stats.rms)) + +def total(l): + return reduce(operator.__add__,l) + +def check_file(f): + try: + print "%s\t" % f, + compare(f) + except Exception, err: + print "Error %s" % err + +if __name__ == '__main__': + import sys + print "file\tmean\tmedian\trms" + if len(sys.argv) > 1: + for f in sys.argv[1:]: + check_file(f) + else: + for f in [ "testdata/" + x for x in good_files]: + check_file(f) + for f in [ "testdata/" + x for x in bad_files]: + check_file(f) + diff --git a/unpack.py b/unpack.py new file mode 100755 index 000000000..f0d61ab3e --- /dev/null +++ b/unpack.py @@ -0,0 +1,12 @@ +#!/usr/bin/python + +import os +import sys + +dir = sys.argv[1] +file = sys.argv[2] + +print dir +os.chdir(dir) + +os.system("tar xzvf %s" % file)