fractalnow-0.8.2/gui/icons/icon16x16.png000664 001750 001750 00000001677 13175112471 017665 0ustar00mpegmpeg000000 000000 PNG  IHDRagAMA asRGB cHRMz&u0`:pQ<bKGDC pHYs   vpAg\ƭIDAT8ˍKTQ?gyG'4jk# -6hQ AE-Z #h"MjY8*31^:ps=?~Ž{LEtLGڦ QjδVѝ@2 A RhHc05EXr1kk]IZZb@`P](  (l+,mm=KNR~}{+ضmu55YuYUfALc-Ϟ=fl=7ouGueZ.'ӂGd s.2\8&ZC>,hN2 #ͫSO.%sK@ E54ÀbF>;\6N؈hN4Uu B-Bj ũs yˢ))nܝ`iqJ#@$PvO1|x:y[DRGFuizL8 'A*08Mu<Ρ,lTR|TU·\( .x^Z3|&7d3|ϲ*PEa(8}/&䌪nnn&J$ʊL8;4PHi$"R)>:KH[ti@י Vfen(%tEXtdate:create2012-05-27T10:48:29+02:00+b%tEXtdate:modify2012-05-27T10:48:29+02:00qIENDB`fractalnow-0.8.2/gui/include/fractal_explorer.h000664 001750 001750 00000013232 13175115345 021527 0ustar00mpegmpeg000000 000000 /* * fractal_explorer.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal_explorer.h * \brief Header file introducing FractalExplorer class. * * \author Marc Pegon */ #ifndef _FRACTAL_EXPLORER__H__ #define _FRACTAL_EXPLORER__H__ #include "main.h" #include "fractalnow.h" #include #include #include #include #include #include #include class FractalExplorer : public QLabel { Q_OBJECT public: FractalExplorer(const FractalConfig &fractalConfig, uint_fast32_t width, uint_fast32_t height, uint_fast32_t minAntiAliasingSize, uint_fast32_t maxAntiAliasingSize, uint_fast32_t antiAliasingSizeIteration, uint_fast32_t quadInterpolationSize, double colorDissimilarityThreshold, double adaptiveAAMThreshold, uint_fast32_t nbThreads, QWidget *parent = 0, Qt::WindowFlags f = 0); const FractalConfig &getFractalConfig() const; const Fractal &getFractal() const; const RenderingParameters &getRender() const; bool getFractalCacheEnabled() const; int getFractalCacheSize() const; bool getSolidGuessingEnabled() const; void launchFractalDrawing(); void launchFractalAntiAliasing(); void resizeImage(uint_fast32_t width, uint_fast32_t height); QSize sizeHint() const; ~FractalExplorer(); QAction *restoreInitialStateAction; QAction *stopDrawingAction; QAction *refreshAction; QAction *zoomInAction; QAction *zoomOutAction; QAction *moveLeftAction; QAction *moveRightAction; QAction *moveUpAction; QAction *moveDownAction; public slots: void restoreInitialState(); void refresh(); int stopDrawing(); // return 1 if drawing was not active anyway void pauseDrawing(); void resumeDrawing(); void zoomInFractal(); void zoomOutFractal(); void moveUpFractal(); void moveDownFractal(); void moveLeftFractal(); void moveRightFractal(); void useFractalCache(bool enabled); void resizeFractalCache(int size); void setSolidGuessingEnabled(bool enabled); void setFractalFormula(int index); void setPParam(const mpc_t *value); void setPParamRe(const mpfr_t *value); void setPParamIm(const mpfr_t *value); void setCParamRe(const mpfr_t *value); void setCParamIm(const mpfr_t *value); void setCenterX(const mpfr_t *value); void setCenterY(const mpfr_t *value); void setSpanX(const mpfr_t *value); void setBailoutRadius(double value); void setMaxIterations(int value); void setAddendFunction(int index); void setStripeDensity(int value); void setColoringMethod(int index); void setIterationCount(int index); void setInterpolationMethod(int index); void setTransferFunction(int index); void setColorScaling(double value); void setColorOffset(double value); void setSpaceColor(const QColor &color); void setGradient(const QGradientStops &gradientStops); void setFractalConfig(const FractalConfig &fractalConfig); void setFractal(const Fractal &fractal); void setRenderingParameters(const RenderingParameters &render); void setGradient(const Gradient &gradient); void setFloatPrecision(int index); private: void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent * event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void wheelEvent(QWheelEvent *event); void contextMenuEvent(QContextMenuEvent *event); int cancelActionIfNotFinished(); void adjustSpan(); void reInitFractal(); void reInitRenderingParameters(); void moveFractal(const mpfr_t dx, const mpfr_t dy, bool emitFractalChanged = false); void zoomInFractal(const mpfr_t newSpanX, const mpfr_t zoomCenterX, const mpfr_t zoomCenterY, bool emitFractalChanged = false); void zoomOutFractal(const mpfr_t newSpanX, const mpfr_t zoomCenterX, const mpfr_t zoomCenterY, bool emitFractalChanged = false); enum ActionType { A_FractalDrawing = 0, A_FractalAntiAliasing }; enum ActionType lastActionType; bool drawingPaused; bool redrawFractal; double currentAntiAliasingSize; bool movingFractalDeferred; bool movingFractalRealTime; bool fractalMoved; mpfr_t fractalCenterXOnPress, fractalCenterYOnPress; QPointF prevMousePos; QPointF mousePosOnPress; QImage imageCopyOnPress; uint_fast32_t initialWidth, initialHeight; FractalConfig fractalConfig, initialFractalConfig; Fractal &fractal; RenderingParameters &render; uint_fast32_t quadInterpolationSize; double colorDissimilarityThreshold; double adaptiveAAMThreshold; FloatPrecision floatPrecision; bool solidGuessing; FractalCache cache; FractalCache *pCache; uint_fast32_t minAntiAliasingSize; uint_fast32_t maxAntiAliasingSize; uint_fast32_t antiAliasingSizeIteration; Threads *threads; QImage *fractalQImage; Image fractalImage; Task *task; QTimer *timer; private slots: void onTimeout(); signals: void wakeUpSignal(); void fractalChanged(const Fractal &); void renderingParametersChanged(const RenderingParameters &); void fractalCacheSizeChanged(int size); }; #endif fractalnow-0.8.2/lib/include/macro_build_floats.h000664 001750 001750 00000003510 13175115345 022003 0ustar00mpegmpeg000000 000000 /* * macro_build_floats.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file macro_build_floats.h * \brief Header file related to macros for building functions operating on multiple float types. * * \author Marc Pegon */ #ifndef __MACRO_BUILD_FLOATS_H__ #define __MACRO_BUILD_FLOATS_H__ #ifdef __cplusplus extern "C" { #endif #define BUILD_FLOAT(fprec) MACRO_BUILD_FLOAT(fprec) #if defined(_ENABLE_MP_FLOATS) && defined(_ENABLE_LDOUBLE_FLOATS) #define BUILD_FLOATS \ BUILD_FLOAT(FP_SINGLE) \ BUILD_FLOAT(FP_DOUBLE) \ BUILD_FLOAT(FP_LDOUBLE) \ BUILD_FLOAT(FP_MP) #elif defined(_ENABLE_MP_FLOATS) && !defined(_ENABLE_LDOUBLE_FLOATS) #define BUILD_FLOATS \ BUILD_FLOAT(FP_SINGLE) \ BUILD_FLOAT(FP_DOUBLE) \ BUILD_FLOAT(FP_MP) #elif !defined(_ENABLE_MP_FLOATS) && defined(_ENABLE_LDOUBLE_FLOATS) #define BUILD_FLOATS \ BUILD_FLOAT(FP_SINGLE) \ BUILD_FLOAT(FP_LDOUBLE) \ BUILD_FLOAT(FP_DOUBLE) #else #define BUILD_FLOATS \ BUILD_FLOAT(FP_SINGLE) \ BUILD_FLOAT(FP_DOUBLE) #endif #define MACRO_BUILD_FLOATS BUILD_FLOATS #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/rendering_files/render04e.render000664 001750 001750 00000000122 13175112471 023550 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING STRIPE 1 SPLINE CUBE 1 0 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/lib/include/fractalnow.h000664 001750 001750 00000003656 13175153661 020331 0ustar00mpegmpeg000000 000000 /* * fractalnow.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractalnow.h * \brief Main FractalNow lib header file. * \author Marc Pegon */ #ifndef __FRACTALNOW_H__ #define __FRACTALNOW_H__ #include "color.h" #include "complex_wrapper.h" #include "error.h" #include "file_io.h" #include "filter.h" #include "float_precision.h" #include "fractal_addend_function.h" #include "fractal_cache.h" #include "fractal_coloring.h" #include "fractal_compute_engine.h" #include "fractal_config.h" #include "fractal_formula.h" #include "fractal.h" #include "fractal_iteration_count.h" #include "fractal_rendering_parameters.h" #include "fractal_transfer_function.h" #include "gradient.h" #include "image.h" #include "misc.h" #include "ppm.h" #include "uirectangle.h" #include "task.h" #include "thread.h" #ifdef __cplusplus extern "C" { #endif #ifndef VERSION_NUMBER /** * \def VERSION_NUMBER * \brief FractalNow version number. */ #define VERSION_NUMBER ?.?.? #endif /** * \fn const char *FractalNow_VersionNumber() * \brief Get FractalNow lib version number. */ const char *FractalNow_VersionNumber(); void FractalNow_Init(); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/rendering_files/render03d.render000664 001750 001750 00000000132 13175112471 023547 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING CURVATURE SPLINE CUBE 7.5E-2 0.5 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/examples/config_files/config02.config000664 001750 001750 00000000236 13175112471 022653 0ustar00mpegmpeg000000 000000 c075 mandelbrot -0.7 0 3 3 10000000 250 1 0x0 averagecoloring triangleinequality linear identity 0.5 0 0 0xff 0.25 0xffffff 0.5 0xffff00 0.75 0xff0000 1 0xff fractalnow-0.8.2/gui/src/task_progress_dialog.cpp000664 001750 001750 00000003063 13175112471 022075 0ustar00mpegmpeg000000 000000 /* * task_progress_dialog.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "task_progress_dialog.h" #include #include #include #include #include int TaskProgressDialog::progress(Task *task, QString labelText, QString cancelButtonText, QWidget *parent) { QProgressDialog progress(labelText, cancelButtonText, 0, 1000, parent); progress.setWindowModality(Qt::WindowModal); progress.setWindowTitle(labelText); progress.setMinimumDuration(0); progress.setValue(0); while (!TaskIsFinished(task)) { if (progress.wasCanceled()) { CancelTask(task); break; } else { progress.setValue(GetTaskProgress(task) * 1000); } QApplication::processEvents(); } progress.setValue(1000); return GetTaskResult(task); } fractalnow-0.8.2/COPYING000664 001750 001750 00000104513 13175112471 014646 0ustar00mpegmpeg000000 000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. 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 state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 3 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program 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, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU 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 Lesser General Public License instead of this License. But first, please read . fractalnow-0.8.2/examples/config_files/config20.config000664 001750 001750 00000000237 13175112471 022654 0ustar00mpegmpeg000000 000000 C075 MANDELBROT -1.50185049 0 7.406E-4 7.406E-4 1E3 500 1 0x0 ITERATIONCOUNT SMOOTH IDENTITY 0.00297 0 0 0xFF 0.25 0xFFFFFF 0.5 0xFFFF00 0.75 0xFF0000 1 0xFF fractalnow-0.8.2/gui/icons/icon24x24.png000664 001750 001750 00000003133 13175112471 017650 0ustar00mpegmpeg000000 000000 PNG  IHDRw=gAMA asRGB cHRMz&u0`:pQ<bKGDC pHYs   vpAgxL;IDATHǕ]Uwf2d3IluA"BZQ"`"`QTE@H `Z`V+[nMd2IZpý^zI$lqÀ\e i6i CáMS"-K)v8NÐC% M0M ӄ²溠R촚M /Y)h q,zyuĄJ 4ժƶ/| xb/ x~$W_5~OcY#l[8qQj= s;WyC0b8|oodQ@*VV"(R?"k@DO&ϋ{xYodziJV MU((*( ^g>|3v==mq92N7M`&!4Cq% \/]y~]}K8W_5o Le\eڠ65fOvYs/u隵LM_Kh/8Ʊf~^QhgMm=} )M9:2?~E&odِ,Bѿ//KF xҥyl[h#'9z1Re47|D$F<$QԩW׸λr\a+/iEj: nw#\.ñ\w:BU״F&M=f.[w8495%IӔ#5289ISIr'&d>DTej$3h}C!w:ZƬ%2q,⤵NS45"MeRuZa(!T**]^C߶,LSqm0E K&4f_G$U'TGbLnW` $dUH9jyoӦumz%tEXtdate:create2012-05-27T10:48:29+02:00+b%tEXtdate:modify2012-05-27T10:48:29+02:00qIENDB`fractalnow-0.8.2/doc/fractal_file_syntax.txt000664 001750 001750 00000004267 13175112471 021147 0ustar00mpegmpeg000000 000000 Fractal files describe a subset of some fractal space, as well as some parameters used for computation. Fractal file syntax: FRACTAL_FILE_FORMAT FRACTAL_TYPE [REAL_MAIN_POWER IMAG_MAIN_POWER] [CX CY] CENTER_X CENTER_Y SPAN_X SPAN_Y ESCAPE_RADIUS NB_ITER_MAX Text characters can be upper-case or lower-case. Arguments separators can be tabs, blank spaces, carriage return. FRACTAL_FILE_FORMAT should be F075, which is the format described in this document. Other format values (of older versions) may still be supported though. FRACTAL_TYPE can be : - MANDELBROT for classic Mandelbrot (z_n = z_{n-1}^2 + c) - MANDELBROTP for custom Mandelbrot (z_n = z_{n-1}^p + c, with p parameter) - JULIA for classic Julia (z_n = z_{n-1}^2 + c, with c parameter) - JULIAP for custom Julia (z_n = z_{n-1}^p + c, with c, p parameters) - BURNINGSHIP for mandelbrot-type burning ship (z_n = (|real(z_{n-1}) + I*|imag(z_{n-1})|)^p + c, with p parameter) - JULIABURNINGSHIP for julia-type burning ship (z_n = (|real(z_{n-1}) + I*|imag(z_{n-1})|)^p + c, with c, p parameters) - MANDELBAR for mandelbar (z_n = conj(z_{n-1})^p + c, with p parameter) - JULIABAR for juliabar (z_n = conj(z_{n-1})^p + c, with c, p parameters) - RUDY for Rudy (z_n = z_{n-1}^p + c*z + d, with c, p parameters) FOR MANDELBROTP, JULIAP, BURNINGSHIP, JULIABURNINGSHIP, MANDELBAR, JULIABAR and RUDY, p parameter is a complex number that must be specified through REAL_MAIN_POWER and IMAG_MAIN_POWER values. For the others, REAL_MAIN_POWER and IMAG_MAIN_POWER are of no use, so they should *not* be specified. For JULIA, JULIAP, JULIABURNINGSHIP, JULIABAR and RUDY, a parameter c (complex number) MUST be specified, hence the optional parameters CX and CY. For the others, CX and CY are of no use, so they should *not* be specified. CENTER_X, CENTER_Y, SPAN_X and SPAN_Y are floating point numbers specifying the part of fractal space to draw. ESCAPE RADIUS (often called bailout value) is a floating point number used as a condition for breaking the fractal loop. NB_ITER_MAX is an integer specifying the maximum number of iterations used to determine if a point is inside fractal or not. Acceptable floating numbers are for example : 2.567 4.146E-5 8.26e2 fractalnow-0.8.2/gui/icons/icon192x192.png000664 001750 001750 00000121203 13175112471 020023 0ustar00mpegmpeg000000 000000 PNG  IHDRRlgAMA asRGB cHRMz&u0`:pQ<bKGDC pHYs   vpAgtIDATxw-u ==y ޒDr-3RS-3!GČzfID))@A(ʽzUyw'͞?V |[AvA q A?ҟ61n;]! a8̯s=|~k<MhՂpe4"cL Q$י$>/=|нd; % 7 \tjƱ! 7׌W<{\~O}?y 4`r TDq&AUu}21-> ZP2\Zq;'k0l|y-s[4Puݳ,":nC -I}Kk妗I"+lVmU+]E&`<6 do47,-9 Y^z0FE&g;UVG=Ϣ{rK/wT}8~_F۳hl2 ]?s;~{N߃`4ffֻh {:TA`ĨmTGߗ{l [羑:]vmz:!PWƿWd5Y Rƫ~1\V]w8٤uO/]2YZr:}nnkz>~ZZ d\=Ou&AılhөŕNЄ;ݛs .>gɝ(KILA#n, ql}QahNݱtPƪx @Bt= G).m_yN'@9~x:/x.$xBFnhz0mz&E';EXhzCYĊcpstqsL&O$_FvX CC8:|0F~Yd砛+}a]+$Vv73@.+ t.] =O_#l&/RyC0J$rQdb{Ā 42~4E8w9'F9qΜI}۰kaşZ7/[Z+~j |jyaLENy3ju*~v9DbpIbI\ }éA-u仏á<ìUPDZ-t)/XU|.;_[[{l>(+2ahFdXNJl.C(S}0|_LssaܔI#|vqUUNYc]|=éa@EFO"SLU"q:(h2!v=ߗ$\KK7j6<VFCVCK&+Dam*atD(p1^5!S !enoyr_G*2:(v$e%['W{ʃ*U]Oِ# $8%d!=/^r z{T-Ι4(Pq+OtM]qG#Yt!wA@G{.`oO1&>m/@/**_t0[2w򽋇k:Շm|BE3MS&&A õ6>lʶ/+f.L&jq^Ej+NGVٌeLIxXNQgp\ 4 fyh,,` +,L~ȷWPl |hLX}AkԭU*(tj"+k !˖=n ЫW ʋ_.2:VtbcwW~kϗxGnM)~/I.cvw%[{#+l&["5+-+qs3So&R(˘2MsT^ZΡX\f\6Er%O}iC3j} ce? %0벺lm嫐n'4o$pр.xuutR7a_qArQnUM\9! :lqp&KK1M+\ag.\RxM}ܿd_ 0oy܄+IDN];-b*"sFJsY %>]SLaDL+nEy0 lok>!N,7rYtB.j4'TcZ=qUX\Xm&p5 mY*Y Kb|_fUN,)(1* şuY0ZN e]ClRǰ&4CW1A \b"ZIn')Hv45P|PՉ*7)4qqj)KWA50ޙⲢEy}z_mM$'+8LqZkv?!8aAsyDѿ.B&y[Dy"ͨ:+eW4T) "N]D&1D5T!|2ı%b=l ^-`I6cLL<oAWZT3ݭHkRYqg=%T*n~z pܸa3JYs/ PFkȫ^9$"qç^$fYsQl%^&hX"BtSk'l& Iɉ\|'y&+YZE=rڂd=&7fSǭ ɯv~6fG}<35IdX29p0 tPj.QEZC2^"DcEplʿ c#tq5\^_hHZ|ܼ92@nZp]$^)(`fF.cU;NrEF9&;Ǣ`hU]&Of<6+C>n7j#b` S7y xuc6|?& T:PtjM[Br|HTqj=ұ77 ө,*gǝqKtWp;dFˠb2BDHN߭TydV0+5.{PiyPpb?5C}pO-|+&H4 `rE=}۲8q>iV`DRiIA+Nm'm\J[ʨ\AM5V^)iX/M(TbaJ4~oZGɪЋ O :IJj4b:<0&˜>8+Wh=vsl}4{ .$54 $3 _9QZ%y oTUmy <ljQ4xERժ_&0ǢUʥ)jP[[w0/e*Z*,ŕx2}l 屐]5H! %x.|/q,+gy 7>埧%&u ؟8}ޢv6P3=867VkEy .&;&mGHAyeP j7IrjRJxAǢITI]qL,,(_A4BznMZt7}9"8ߣt\$iӶ\Tԍtb%48aL`f-H.H 7?~ c-ݛ4{lŗxm%. ޤOol m)r)~jʓr˥Icux1$>!K ?p{+;~ˑ_$ދygN3~~_=mҎk_a7F4| b3bn@5rx6w{~ƒ v,\ k V1u:3vw%I*>BO8fVW|.%ڧx84Q[v\,~#a&a&X*]͓JkۓcmM ahA[C)ʓL,L)qeiiZY+bIYV+$ kam;3flw2K{'E!s['>8n@!h>8&óS٬Ny1Y=H#@.~䘖̪L"gpO>VZfE"WNUH0_#-ZhQTjCX׭R/uYct:qB5{Dq9oժFıf_✇3 P;1Q0'/pϑl F|拄au%1{[ܵY}.s{K'`L" Nf~6ZTźpڌ! |T+:yIȨE"wCOLdԢlW) ojRCosItHI"wBٮI$fscqg҄Z &$>N1d*zݮP^=F.td~13`2 3c1`ݵۜ>n[ǭK).1xyY<љo51]Vˤ_K0Q„uΥ$F#ShO kjHLd*2֖͒V弁kN&6 nK˃^4;']dUUɫ~L k]Ih%- n*UfZ*+K'^?HU,6d[Z$`F`|`r4a Ucxސo^`->z~ϯpCF87F0]pð #ĵ3̧шcgYZ)ս\Ef_U@awWܣ|wI}U\;AwR]ZqeZ44I"Qv.^5.fb_RQq"WD叭gyN0'nh5$NJk$e')#h`<SCs{1qs 0pL1> nrﯷYmccgPa>:ivp$<CNc3ù@)˘N7gL| [[~F 3'T}Gi=pc`K>1Ʀs51bLx4F&pn?Av Ak9Iw"^ds]]P?j)I\Zr)))>)oYܺVwkF%6*+zp޶El&;Ir Z>iT*-ˎ~?w`5*Kkx7Ę) .cj=qn"A瑷`k'Rc2=\ f#3Ab87` {:n|}{{鄺! !8t ݏ9" }3Av%~dԾv{T D0 Gxn,ROp &_L[{6|--Х;X}~P]Һ#GtBشf5k Fnnȋ%(^^%'e="`-U*k0jTKIbcW Gcl?2G!7Hk\ 8pz{f}ŇeE ?0Խ&[毿eN&$5{׻,9FZ% ٻpM}@=ݝZ8F9xFpI%:$vcurW:hT/Bj[ɢ\U[-/o,P5m9y$."H}=zQ*(b ^R-JҁRM[L0JrMe׋`8ZZ#| ֎j4.bx-aWcb?<6n,}k~~s'M_WlҥKch^k< _ƍW2iw#G8{ٺo5v,>>2O%_?yuԏV !Bܱ[>"8k`&xވVKt]PwS\h5\fj5gmsle U 2p*x͹рcލ9zB1M?N%&Wپ86j<&.QddK4nSX9Q:UZ]N$҄Zo2&UZhڦf2~U.Uq;+G*"4svMJN*N03k)$14KH7Ec% TaG3ʄWO2۳\Q7l9?i>ǙombkEls<55d &b?kni|0XK} Oydi#m:G@%m^f﹋$P։%LWcpd ^3J+ǹx˴pj>̋/sH;Ev%ZtN&dbX|WTMEF[`L⎠ "fmJ έ2]O) yA던$|FzIcmC2isy/Nj<6c/s˟.C&!/o񥍘q8$I"i+=\0 /m jm he] {ny{^& /ah\wU{truT^ᵨ(gTcGL{vM|4\YCZUFX5SdE3 Bz?}Lá-( W{hU!1Tf6s/\ ^_8RC!C!Yex^KB1%ݜ=/4d,{[ ?p28Gf_g`} _8ί],^Y`]u'[v,c]H%1xl3d21Yk"DR^Q$+j3?s劗7 jeD(N:T$sT>vrx,//ͼ2Hr'Gdw $Hv>!r }Ctf4!a`قigug8SK32Bs_y>E*&&u־gz;hH-ub(7("Fq ڼ&KU}ɉu9c6Op# =^qT,YdP vv,{{y"-IoUNng6P}[Z'<?ZZUA5mM#HkgloR3ԸMauʠ}(z)dc@Wu+I >]ORCpĬg5^d2f=;0d~8{\[?+ “kUڃ4N8CZ3~6ְ"]{!  F#QVR (_܊\d_? B۲*zY.U4誌AA߫A"s|=)z6+_nh6m**75>wԂ\'j9̈́VsR1p$M:/ HW&`mpC8tyxI~w0ek|l`0ᒄ]~]'x/~|rϘao-L֑hVzH~_JmQ\tz(^Es|m' __wllJQEwbXUJny&Oz.+ϛFD@O'P$c18%`4%LrH%>'; Hy1zB S<Ϧyczv Rtm $%j8<-ͯOc?F?'CV>N=%opMkǖLwZt׽L*JWBx5 h~12<aKK+V4lN@oZ-; ەr-'y*3hvũ;efSYz!:I:|_QTAeY6  $׈'x]z{~($MdyscolF6Ф<ƌ5}3[NmLp&Xʹ_+@IG!1|-\Rh]]a}廴W9qQuX$mUci/dJ#.~"\cd|W_|x#\ Y i݋!Uw#y8L[txtW<,U";w}ћRR0LU.W}~z=&B%sK$gv EmIvD&ք3x \gX8!HO!&XQ?qu~f)/ϰ=sm(QoĿj[}5'1~/݁B>*wH=l}pVѦ;?" LJWրSEbRc++¹Q Ez}l4Ⱥ+tHG1"}< Ds$N0fRg{9 #0b6dB`#}_c}ƀ3XWיNl}v;;5EctDI;^SoWppq Vil0ERvUCyT?ş7!FC])YkƔ.TɌ* Jڐʤ;zEq&HC&"b;7<]j3f3/C4/#U~.(+IU1iZ>;ETM) [*gb^DGl.pc8$V]Zv# a6 Rx(5L&&D6d+VeD\ol]zZY0԰``p)%ر)d1 7.G>g\0o Fȍ/9%Ã:1}|]O y!ͦKD^~"_ţ rk3lѾ=ݹAj11xm#j ZVu_ʉ-m;^ă,/B`+?GK IK&x3JJm\thSߢn~szt 0nI.vp &;//^_&?:y8ͯomc&RNx"lؗRb\nT$-]&&ӀTZ5:rBS&^5049mQE֦pFUj8"V+^3\|dI6+n`d ;gf|X~6oׁ.X 3o|LOoqs-t8;S`ѯq;Js{pN ~2'O}"+܅! ܊NA/.*l$._l]XqKQNEԝO vJCl&>tB460xm}أWB砱Z%Ipi5IO"D;{1xg:aL\ iJ² :SN_xkx֐oc43 lti?u$Iff@H(V(jOHR HT![tBn{]y\~j3uxx8ä0c6K ~j6وoc廆]w ~\9lʻdq6.R#T.= `: Emp8Tiyű%d\dZ5*Z}o.KWh[WyW-^PSeCTJjtXBgcfsB8WOa,%KZHj$ =010!0:r?wM<׸upoavgγlkqQ^?VǼ^zWF˽GY g}+k5[\:7?|4O#\V5?b}˕gorar&D@ E%Ԓ25ףTYZr@M\ݞN\3Sxbw{,F+D|~Gu6M\t{غ }4K#?lsc~e ^%o p{7>CoqM=оn.J: dGݗppQ%l8CwG>lcri Wyi9 c1͗%K]ZOyj/VkG)!3˜ #sn>:kY%; ӐxM;;Hë<F཯Q['{\otGBD6LiO{tyU6Y(;XT3dISWUA ZB7yN59T'u T5~hfV"# %Ȗ &X4RIQfLp%i7$zy˼6l8X9\∦S.޺a'O~wnolïqΟ}2@jȻ,\0S:Ibm"6q~hvV_s,ǔK2;=IbR}IH=IRxJϑl*.d1@XC!=0Wr6q{e_;lsg2#Q7uZ_z$Oum!fW7i8GǼϬ op˒QsQL,3?(ƔpQ^ 2bSZ$"$;"h!5ve;C4 tЧ՚yQVeU_1YHy2ֿ3?}TKw)o'Cqkiܢe'\3}mzIkj]qR["fGylVե" ;Y]gC=,ݮA>ttd=4Kڗ@bD~DPI#16߄hHpKickx׸gV㣫_U^ 1=>uWSE6)F[^V u*j~/6TA'' HdW4Ʊ$Ea*/gi)*dbS'fAzd􁚔Ebs^ 8K!ƎGϥ5{`Xb|C\`Jc/}÷|2')$OY0 CIp y* b jT4v\)=/2_UxDHRyv:.J٤ yi\+4!L115DQnS ebLϿ}m4]N2xbMW<>7AQLJ~^wkoyDW-g ~ 1EDPV戀ʿ(}5Vw%c.5! f3ۓ^ODХ ˺wHܠev;Lkc|煀~L{ҏ] R(MiyI6U?wSMa|7)&n`8M6yD:|nMƛ5y oN kGtb+?Utu(6>1L4s˜d+=p63T&pv(6}c£1BKqFI:n[ayY $w\~{_c001 Y;qfׯ|NG Ř.uSKc>#JE)z43ݝoQ(lK],9})\NEVNn C,I H$m y cO9B#]̽t!b0 퀻a0>o&0e:mGN/smlhcW$./|()v#G׫;{~1Zߊ1Hu5SqUDrDJ[P!]_fs2(~/W)BOtmj@_K[jI$UZ!m .yu0K,L!&xo&JA|s_]cK sq˸y",wVz<] 2H7msUF?K +ANx?#I+'de2s 5°s k!R`Z@;U]htg4? 8u0]`cV01Y500@ b;aős_xyn ~G~;no\z71E|!s!gX޳4 iI@naڴ+AQ!˼Ii9&E0+0O)H ԢZGYA5bRQ.Ц4ZlI/Ղam i` A4 WS,-pqc%"D`lc+<& ]WgClxc7#eYM:a3~s$g?u:kj88ϩ PyХߟOI 5.ݰa4'RD$n%5'yRA,^=lY7]8́u Q:PK5A iےA2f3d/43<ҹ|kC{t^Ř%y^ͨ=@ Z/386jA4PK&bY|%)?dREupM 1v1%&si:QE1jk5D{oCLUJ&VIIP3KIw4Y0 #.:h[ׯi;~cx”윣кy Otb}.wG>]%k*N<^w QYJᘣ7s!eUχ+UeaZd&cKHMڍ\o"rE'ڱ"(M˪y>jF'O6JAuFs?@ b-z PI.#ĦI;K0X.aKG (c"[x 3`N0~uRx`m?wWwqOD4gy~g9~4"KKVlhx^ #r=JCKTV'\E"}Тnق4s6%-KPQmbc/i'QTf6|?!"f3ԣ^OHsKx cNAm- @* ݢ]}|tW_j1q?pQRvQ~[{dp9o 05#Noy8h6Jjıe4(V*" Е\*&Cߊq< U3F.lwפmrK$Pt3ͫSj"oë:Ѵ5+(f^&>ohz1`$>TYCK4ΜDiw^7YwCs'x~_ltZK>䈇>t s`oAԒ4GN,?3 nSh+,*y%ePn;V _n?_W{my?UHؚa+P@$٦ti6dh TbU0L]؃#h#uwk[w5p+}|6>3%IRD qtx+5kܳrv͛?po>O6sƈ9aSh;|BxxZ4>1A@i\DQ*ͦEE?{^ަ[,F^$Xb/Y41ikfZ z.nQ<@16c/ iaŹm$!qU}Ϭ1Ɨo}tSa#l0X/o>O|YRnSgrB̈́Mzt.g:=o}dx.C`Rz"x#8*LZ^Ku҈_\_YC ד7Z t c0Y$GU5w$V$f-:fi8LҲJG:q :ˌg#2U5e׮15O` kse*?xowz3o߼EO!Njry>^}Pt?qlyˮ"j1ηII!©݅,UsDcIXk MTr(rX .5Ө~I!\/-sinUN|`*S-ocO>lc)}^ˈoF^3]Dpͫv`W6Y^R!&^p( gl(tb 2x/ͷH iAډ>ǭ:G-i⹝HËڍz{(,BjiIfޞE(z$bN}KLL 40 pH6?O3ZOX}ǐ޷D{ {ve[s RZ0Ѽ>WnSY?کL\is l5 of`2{W~ev ךgl-?=H'i<cSbQ -On !܍ݥ:v.*$cm#o\Z'a*&0JZzc =uT@)Hu@c8M20rZ_6R xܧ~XE St~4 Ƭ54B^8 |8d_cgog|ή?'=^]봻Gn]Q[ mP ZI%G\bV\xˋ:ű?R̪E.+ANgBk!FοT!8]~l9Vx/"h,%㫸x㭀!-Rg->kA ,)πqRg`X])5Zkibr+<gY 8{o{yvvghe |1sU+><+̼Ĺ&)i\b,uҖU?幟GΥEz&Ӊc.]@[lpfe ˘Zx%d>e*\1|^6bH.Yq g_9ѿ)_D/\~dMYLmkH uKB,oS$"/ M&Zf3?zک&IR9Y4l dV~AtM=&783|ܵ&3Yt{?;w:{z6!&۹`/Q1sB[^?ŀ4čh\IsR8}W\)~ b|;;yXǕoP: 芡nW-J񑑱ciMc/m& 9I'i0RqLKRL&z nbL[±_blu1ZO]inrS\2gK?c .q ƛ>׏ӽ\AH5w%l1XCqc ȑnd ׬.E [4VW{y2ʧvGp|UJi9%$9b[&9QNg`ݎͼLHby8eN،wᏉ8 n`<7/}==9kԏE_/HU-uou.s7($q4V )LӲ;E d9 tfIm .T[/pH)|)¬ MD1Yym>d:0d6%eljf6NGS._nx d"s+ෞy ~l^}?K/x%yY4# {ϩ~^t[o廖\/?ʉ ;;ӍQm9Ct͙#Ws7G؄{XYtat$|Akyi\U8pC+0~TE5u*R>Oq+!""pH*Su)4$5fETUL_jlwc|?b6kjQZ2{`40ΐXkć~ S5' ?78lFl7IO1c=j=ɏOdT.wRIݝSyI02MzQ31ƣ^b30)oȘ/G=8;O}u~=>O7<uϿ̥~,f8$g[GI0_لǿ=m?I}Zz<]i_\{7k?: rS+\#K7o8q|7.XbZ$}D9${6Syo^Q::: ?37Γp(ͺ5 0t9Vt=1ιRRtT~kH;(Q՝Rd:QT̄ vw[dS% FEHp3m:g8|/]\|컯w+Ӝ6S8~g.Yڍ:zGonMyk2LIs1oH+{iMjԈ=;OMU_cNtMRc 'mt|rJGhfG4'֟$K@;c~Z+1C7b7/Em"ͥPZ["rgF2 kŃY 9Kh dND:g.Y5xsHq W?^w4jx^x1|ͥk5CNV7 ` Lkk~1 zԎ.kr5n]Y㞽Gm1+]۷fY:W}{} t/h|jgL1 (/' O@U*/*i+%PUO:Uj6]بS5X# 60w6R\̯<(7.NU"! gw-Gq#ck}n9+>yOʣ_Xd_{qDFBp3f[#4kmXm-F#?5njqƼXg|i%7-b:o˗]>Aɳ" ! nh$*p\\$<*VM&}*UiEfkqפ9LD ,Ƙ!{XP8:{\KԎEdէƀ$ >p:`|:0J1^sM?}I !YjvW1k9Amɣ~q0&lc*u: Z|$9tE.U6^fCŝeeOq[T՛JC% dş5,Ao+\1X{>hc._ndiBdXS4cXAF1߽N N@#-0'mPlݘ .áiN,5[Ԏ/O8DFҫ$mGU,Zy'dkZ=:5M Q0iޠ= Edk);b5W.U K'!`t{ ^t&k5-p].r;8WO QTZt|OE $L^\ͫv9$6ɗ̨s]bH_U G  r|SRu92b,QcyAiSqJUTxAQLKcL$c,!5Qΐ1Kbxn!{u\ rᷛ49:SSVpti&@\"M$Ib՚F~!5HFRpQ1ፆ4;; h0I)KU,Jg_\Ţ+e-*4aγP8l<&EV LRdd8<eǎqi ,:M̋ O}ӽ4mKpP|~ 1&& ǟ$^;Ilh' KnS :66gr}НW-UP/lzX1Aq^:z=k IJk= & E闱X^YZclAyq(&]YXeevAAq6 wE~s@m6]f,l{9Svs4QZ:+ʰg2s9\N 9$W<&A68ln53*v5g`2h^wYXW\PJ7t"]0-.l`k=p=sWp!WIDAT%mw7o\x xW8{L;7=B{pdwD>=f̌$"vE"|ph֬B_c>IC(<-gD,`eštEvWEwZȎpЄŕXZZ(Ua8QY~eZI 0'N\%jWƔr 3ʚSjwOW6I5rrKI}QZaV`zou:\drC*=ax'o`^~5ܹc ɐҸoFl jM0+DQ;Ħ#mL\|Z gGʻҿU%V1r($"rJU~vNle(8ܣd7uR~Uq)9M^}!)rT̈zS=|}_ L5pϛF P m8 z{Qc'0^]Af(]s*X筧\=4ޱLѻ0ivjǁD{F#0 YV4^inHT4IC1Xeɱ栯xTves-k*C[_()VPhd3SLoj&/ voi b Q|6b#ѪFCifzN9:cwf:]i!Ƅ0l1ŚR.1m})'_ ~i|?vR?r84_F:% өEJr4@J!ؾhy Q; `eEj';Ajw0 ]L0gZ ʂ;uc+t!8(սz?K&< RŇP,++\h$ll&7~uǜ˹(s9KyPYlVKuLʛ}Zmꑮ- 8?d5lm؅lLhh5+~s"d=嚋M`{:Y4Vs4 ㉟UpY9 ƂKp[t_;J Sù mDץl(Uc4udm(РnaN.Z͋DNVT< 22*7Z-\vߣMüdWTP53 WU,N$pe5pmѪ (o)'9u+Hp`r15u&ny^Xj8b نZ\cz)ѽ=IKw<<$A׎k%77)#kz㱸(ݮYKQFt8aQPv&~?p}Wդ(~ IS UIʘ9ZF[{ ~Ѳ_vΧmA5ZUFMu-űZ-4]5IR(IW G8]8En1z* > ^n7$X[BkEJf3I]-snB+ȹ+KXZZ^ RmUA_0h:UT|=q ""ҋ. Ѣy]:zTloUA{.H1VA&|م/Mt-\Qm>Σ eGAbM!iѸN E/- 4)y`̘drkmXx=F _oltYo8Dxphӄr,-EiGG&QaJpzhgWWcue ]4#~F)Ǥ.ʪ&arfݴss<R^/GdT,!$?oR2Dd4>'.4֤/;5N?Nq \\։L\q0Ҙ͹X^܍k zQr_nW=.C 0&LֽA+iI% e(uX#Fx9!mkKQ]Q4XZy}|L߯lf2jv@P&N 2i)hU>)S)T"|yYm+aXbኼh(佨-ө|i|Uq~UV(*WzSP!h(x+\>juh4ޔQ+1Y)܉" @xTɞ+u>d" 1f_P54}aAjZ25:V2>.mZ8U6[;&CDeE_|qՐYQդ)i8[dUiq-Orlml/dXxZ۪TUdPTZDS֖0f3J;JATtc2I:;=n.CUo_^ʿ]kT'I\]]eg'Wᖖt:?tѩZmc~gHKRݲ"lni,gE|UqQ$6Q(^ UП<QC]{0UYEh%we4w kXAKOG%%&*8)Pwj:5Yi^H8,??U||d !kRߟ, 坦O@zDlвrUBη ʐ(׽=>S>W2:+ WnvEi,^uoU}iI'Lndykq,vJmaR '~Km^jF)V.uVʋ[y(Yq>ܔUsL8Bjk;,z8&3fSVTU.MI~UR}AWM"M)]SDZ \!p"$5(bMPo)5!oMT( Z.K)9ĨM4t1>;+8-'_rg^Y2gr7o_E GU_e,ce*+pIdK,b5|[ĪIR51Vq.2Z-WH-Yo> }d)̑{1sybRņU\]8v ɄN3M))dz"CVu6szv=2$@!!J,HSJgӵX^dBf@b8OF#e`9X8/$׆e> )cUR~8jH6+HrVc'y[91ޞɠWKτ"M%,f,+TlMZ|A.nUi6W-.Ȁa)bJ,&&V,@f\D倰h{K̨N+{U䠣IwWjRuɋ*ӊ[|G\96s@y"(%0M]c:-C+etbq3>\jneac⸉gRV1Li)Z,J~,b /2rAL/Ea:}c*j4Pw2Y5!u.kZ_h4毯/r'Qj|#&I+(QKgc7J_|^ڮVGs06Uu7B7wPhNn.|=kk拫ʢ[/B9U_tY3_)z KV5ѡWbeEc+CZ 9>?j]5_ņ}wrx/dѼdh̃jFVixEO&Jq4&sjN|ް\Fu_}8x3e{0pYM(Em}zWr%*/i>"2ͦK]Yc\:E~oi6]V(޲"i9w2~9EO}9rZ\ߴA_U-^MƫYAt!Rd'V1+&b$KUƃ\Pg[~z$ p]fדIcEJn~ǟp <JӊjpޝF rnS*k)nA/K\9.\<>*ߘieyQ iـ|v}j,pPp8]ǡ|MZ_STVk}]h&P,?hD] /_>֭dN_kd T E!E_V*TYU.6Z$. UQjTck~fűZxo׸lUGlN^evgxRT2^7VdѦamkYݮ 8lZ`yAeM]oъv$*OzWڹ֮ō+OwKc&Cu4`H&e!] i8G !B 1&1972IK1=}dAh%jgfgM, E&feNT'KÕ:V%i!M cD) 'b=m·~- d->vyC9OŘ0f9͞j /:Okzb7чZh O7oxdD N?1EDeY+ BdC8fMt]3Oi ^,*{XQc J3|:uU6$R?$Y-U妻 neꢫ)oY>]Í1SpN2S{F# ^S6U<b /G}_:"b0p]ld[e~e,pӖq<|YRy^ăS$_.{Y+sXe*iz&HƘ$H{CBb%lgAc6)eUm|2Vb1چ> VcWH ƪ4yB^ThJQ8;lqW5|s ST~v &880X,‚->L},eؖu= ~Ћ/YfJԕI4 vovY_,c]H>W>ۺ<'dTWѦ:;Ë_U6ewÇW 1%ޱ|6Mвic"cDd I;|ON]gں!3QKܞm!`!h( 2/OM{X&~%|j-28伢p^aRU=k1+ @T{-E?Ϧ 6M]e]Ci VUX m;d`p 6 ܄RF uhdPHMt ~_-9}cg7n(t۷c~x>( \*KŒFtji߁p?wgǵ$a̘t^bR3&ID{cG pةgkQ}Tեd\-vw@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "fractalnow.h" #define STR_EXPAND(tok) #tok #define STR(tok) STR_EXPAND(tok) const char *FractalNow_VersionNumber() { return STR(VERSION_NUMBER); } fractalnow-0.8.2/examples/fractal_files/fractal02.fractal000664 001750 001750 00000000054 13175112471 023336 0ustar00mpegmpeg000000 000000 F075 JULIA 0.5 0.25 0.0 0.0 2.5 2.5 1E7 100 fractalnow-0.8.2/gui/include/task_progress_dialog.h000664 001750 001750 00000002364 13175112471 022401 0ustar00mpegmpeg000000 000000 /* * task_progress_dialog.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file task_progress_dialog.h * \brief Header file introducing TaskProgressDialog class. * * \author Marc Pegon */ #ifndef __ACTION_PROGRESS_DIALOG_H__ #define __ACTION_PROGRESS_DIALOG_H__ #include "fractalnow.h" #include #include class TaskProgressDialog { public: static int progress(Task *task, QString labelText, QString cancelButtonText, QWidget *parent=0); }; #endif fractalnow-0.8.2/README000664 001750 001750 00000004302 13175135232 014466 0ustar00mpegmpeg000000 000000 FractalNow Version 0.8.2 (2017-10-28) Copyright: 2011-2017 Marc Pegon Homepage: http://fractalnow.sourceforge.net/ Description =========== FractalNow is an open source, multi-platform fractal generator. It provides users with tools to generate pictures of various types of fractals quickly and easily. It is made of both a command line (FractalNow) and a graphical tool (QFractalNow). The graphical tool, based on Qt library, allows users to explore fractals intuitively and generate pictures. Both tools are entirely multi-threaded and implement advanced algorithms and heuristics that make computation very fast compared to most existing free fractal generators. Features ======== - Intuitive graphical user-interface (QFractalNow) to explore fractal space easily - A command-line tool (FractalNow) that can work on machines without a desktop, and could be used by scripts to produce animations - Several formulas available (Mandelbrot, Julia, Multibrot, Mandelbar, Burning ship, Rudy, and more...) - Various types of coloring available (Iteration counts, Average coloring methods) - Multiple anti-aliasing methods (Gaussian blur, Oversampling, Adaptive (intelligent)) to produce high quality images - Advanced algorithms and heuristics to speed up computation (Solid guessing, Adaptive anti-aliasing, Caching) - Entirely multi-threaded to work even faster on multi-core processors - Ability to save/load configuration and gradient files - Support for multiple precision (arbitrary precision) floats License ======= This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. 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. fractalnow-0.8.2/gui/icons/icon32x32.png000664 001750 001750 00000004530 13175112471 017650 0ustar00mpegmpeg000000 000000 PNG  IHDR szzgAMA asRGB cHRMz&u0`:pQ<bKGDC pHYs   vpAg 8IDATXÍm$U[u룿e'Y@A1 d!1"@F&&@ٿc&A0FL4FȺE,awzfzLu(k%{=瞫|68"0ۆ 0&( <mhl&a:UlmAJ cۼV-9Z/ l[ CdNȜ jd~29-&T…gXo 42(FB 9ı" is1e uŎAQ'ժ@]hEj0FC>GTiǵRD*$Y&x()2&IKA /SEn%:amOw~ƑWSw\@f<{ٮ4/8c{uXjB( T4;%C Oa'Oq?GOrxVrc< `iyJ/RM㘝{о/سgNBo<&FsV9◾gc/0ISl"eXlolf<1y~unc}]_s|-9+fBÞgkXg8Tlm)HıVπ+uN|̓\|픯v#(Ex!b'|Qѿǵ[hd4@z<:a2,2久mx|ws{`THuy^^x=wʲ,mlϴK0I!*ۍ )DePKpxW/ނU ,|_>18^&MEdvI81T^7ZyR'ofIAIM&R%w+\[,,v I01LԽLB%tEXtdate:create2012-05-27T10:48:29+02:00+b%tEXtdate:modify2012-05-27T10:48:29+02:00qIENDB`fractalnow-0.8.2/man/fractalnow.1000664 001750 001750 00000005201 13175115345 016605 0ustar00mpegmpeg000000 000000 .TH "FRACTALNOW" "1" "2012-07-11" "FractalNow" "Fractal generator" .SH NAME fractalnow \- Generate fractal images. .SH SYNOPSYS .B fractalnow [OPTIONS] \-c [\-x |\-y ] \-o . .br .B fractalnow [OPTIONS] \-f \-r [\-x |\-y ] \-o .SH DESCRIPTION FractalNow is a command line tool that generates pictures of fractals as Portable PixMap (PPM) files. .br It is multi-threaded and implements advanced algorithms and heuristics that make computation very fast compared to most existing free fractal generators. .br See QFractalNow, a graphical tool to explore fractals. .SH OPTIONS .TP .B \-h Print help. . .TP .B \-q Quiet mode, only errors are displayed. . .TP .B \-v Verbose mode. . .TP .B \-j Specify number of threads (see help for default value). . .TP .B \-g Specify gradient file, overriding gradient from configuration/ rendering file. . .TP .B \-l Specify float type: .RS single Single precision. .br double Double precision. .br ldouble Long double precision. .br mp Multiple precision. .RE . .TP .B \-L Specify precision of Multiple Precision (MP) floats (see help for default value). . .TP .B \-a Specify anti-aliasing method: .RS none By default. .br blur Gaussian blur. .br oversampling Oversampling. .br adaptive Smart oversampling. .RE . .TP .B \-s Specify size for anti-aliasing: .RS Radius for blur (values in [2.5, 4] are generally good). .br Scale factor for oversampling ([3, 5] is good for a high quality image). .br Scale factor for adaptive (integers between 3-5 are good for a high quality image). .RE . .TP .B \-p Threshold for adaptive anti-aliasing (see help for default value). . .TP .B \-i Maximum size of quadrilaterals for linear interpolation. .RS Default is good for no visible loss of quality (see help for default value). .br 1 means no interpolation (all pixels are computed). .RE . .TP .B \-t Dissimilarity threshold for quad interpolation. .RS Default is good for no visible loss of quality (see help for default value). .br A quadrilateral that shows too dissimilar values at its corners will be computed, as opposed to interpolated. .RE .SH AUTHOR FractalNow was written by Marc Pegon . .SH COPYRIGHT FractalNow is licensed under the terms of the GNU Lesser General Public License, Version 3 or any later version published by the Free Software Foundation. .SH "SEE ALSO" QFractalNow manual page. .br Documentation files describing configuration, fractal, rendering and gradient files formats. fractalnow-0.8.2/lib/src/fractal.c000664 001750 001750 00000103354 13175115345 016735 0ustar00mpegmpeg000000 000000 /* * fractal.c -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "fractal.h" #include "error.h" #include "file_io.h" #include "filter.h" #include "fractal_compute_engine.h" #include "misc.h" #include "uirectangle.h" #include "thread.h" #include #include #include #include #define HandleRequests(max_counter) \ if (counter == max_counter) {\ HandlePauseRequest(threadArgHeader);\ cancelRequested =\ CancelTaskRequested(threadArgHeader);\ counter = 0;\ } else {\ ++counter;\ } typedef struct s_DrawFractalArguments { uint_fast32_t threadId; FractalCache *cache; Image *image; Image *copyImage; const Fractal *fractal; const RenderingParameters *render; uint_fast32_t nbRectangles; UIRectangle *rectangles; uint_fast32_t size; double threshold; FloatPrecision floatPrecision; } DrawFractalArguments; void FreeDrawFractalArguments(void *arg) { DrawFractalArguments *c_arg = (DrawFractalArguments *)arg; if (c_arg->threadId == 0) { free(c_arg->rectangles); if (c_arg->copyImage != NULL) { FreeImage(*c_arg->copyImage); free(c_arg->copyImage); } } } const char *fractalFormatStr[] = { (const char *)"f075" }; const uint_fast32_t nbFractalFormats = sizeof(fractalFormatStr) / sizeof(const char *); int ReadFractalFileV075(Fractal *fractal, const char *fileName, FILE *file); typedef int (*ReadFractalFileFunction)(Fractal *fractal, const char *fileName, FILE *file); const ReadFractalFileFunction readFractalFileFunction[] = { ReadFractalFileV075 }; int WriteFractalFileV075(const Fractal *fractal, const char *fileName, FILE *file); typedef int (*WriteFractalFileFunction)(const Fractal *fractal, const char *fileName, FILE *file); const WriteFractalFileFunction writeFractalFileFunction[] = { WriteFractalFileV075 }; inline void InitFractal(Fractal *fractal, FractalFormula fractalFormula, Complex_l p, Complex_l c, long double centerX, long double centerY, long double spanX, long double spanY, double escapeRadius, uint_fast32_t maxIter) { cinitBiggestF(fractal->p); cinitBiggestF(fractal->c); initBiggestF(fractal->centerX); initBiggestF(fractal->centerY); initBiggestF(fractal->spanX); initBiggestF(fractal->spanY); initBiggestF(fractal->x1); initBiggestF(fractal->y1); fractal->fractalFormula = fractalFormula; if (fractalFormula == FRAC_MANDELBROT || fractalFormula == FRAC_JULIA) { p = cbuild_l(2, 0); } cfromCLDoubleBiggestF(fractal->p, p); cfromCLDoubleBiggestF(fractal->c, c); fractal->escapeRadius = escapeRadius; fractal->maxIter = maxIter; fromDoubleBiggestF(fractal->centerX, centerX); fromDoubleBiggestF(fractal->centerY, centerY); fromDoubleBiggestF(fractal->spanX, spanX); fromDoubleBiggestF(fractal->spanY, spanY); fromDoubleBiggestF(fractal->x1, centerX - spanX/2); fromDoubleBiggestF(fractal->y1, centerY - spanY/2); } #ifdef _ENABLE_MP_FLOATS inline void InitFractal2(Fractal *fractal, FractalFormula fractalFormula, const mpc_t p, const mpc_t c, const mpfr_t centerX, const mpfr_t centerY, const mpfr_t spanX, const mpfr_t spanY, double escapeRadius, uint_fast32_t maxIter) { cinitBiggestF(fractal->p); cinitBiggestF(fractal->c); initBiggestF(fractal->centerX); initBiggestF(fractal->centerY); initBiggestF(fractal->spanX); initBiggestF(fractal->spanY); initBiggestF(fractal->x1); initBiggestF(fractal->y1); fractal->fractalFormula = fractalFormula; if (fractalFormula == FRAC_MANDELBROT || fractalFormula == FRAC_JULIA) { cfromUiBiggestF(fractal->p, 2); } else { cfromMPCBiggestF(fractal->p, p); } cfromMPCBiggestF(fractal->c, c); fractal->escapeRadius = escapeRadius; fractal->maxIter = maxIter; fromMPFRBiggestF(fractal->centerX, centerX); fromMPFRBiggestF(fractal->centerY, centerY); fromMPFRBiggestF(fractal->spanX, spanX); fromMPFRBiggestF(fractal->spanY, spanY); mpfr_t tmp; initF(FP_MP, tmp); div_uiF(FP_MP, tmp, spanX, 2); subF(FP_MP, tmp, centerX, tmp); fromMPFRBiggestF(fractal->x1, tmp); div_uiF(FP_MP, tmp, spanY, 2); subF(FP_MP, tmp, centerY, tmp); fromMPFRBiggestF(fractal->y1, tmp); clearF(FP_MP, tmp); } #endif static void InitFractalBiggestF(Fractal *fractal, FractalFormula fractalFormula, const BiggestComplexFloat p, const BiggestComplexFloat c, const BiggestFloat centerX, const BiggestFloat centerY, const BiggestFloat spanX, const BiggestFloat spanY, double escapeRadius, uint_fast32_t maxIter) { #ifdef _ENABLE_MP_FLOATS InitFractal2(fractal, fractalFormula, p, c, centerX, centerY, spanX, spanY, escapeRadius, maxIter); #else // #ifndef _ENABLE_MP_FLOATS InitFractal(fractal, fractalFormula, p, c, centerX, centerY, spanX, spanY, escapeRadius, maxIter); #endif } Fractal CopyFractal(const Fractal *fractal) { Fractal res; InitFractalBiggestF(&res, fractal->fractalFormula, fractal->p, fractal->c, fractal->centerX, fractal->centerY, fractal->spanX, fractal->spanY, fractal->escapeRadius, fractal->maxIter); return res; } int ReadFractalFileV075(Fractal *fractal, const char *fileName, FILE *file) { int res = 0; char tmp[6][256]; BiggestComplexFloat p; cinitBiggestF(p); BiggestFloat reP, imP; initBiggestF(reP); initBiggestF(imP); BiggestComplexFloat c; cinitBiggestF(c); BiggestFloat reC, imC; initBiggestF(reC); initBiggestF(imC); BiggestFloat centerX, centerY; initBiggestF(centerX); initBiggestF(centerY); BiggestFloat spanX, spanY; initBiggestF(spanX); initBiggestF(spanY); FractalFormula fractalFormula; if (readString(file, tmp[0]) < 1) { FractalNow_read_werror(fileName); } if (GetFractalFormula(&fractalFormula, tmp[0])) { FractalNow_werror("Invalid fractal file : could not get fractal formula.\n"); } switch (fractalFormula) { case FRAC_MANDELBROT: case FRAC_JULIA: fromUiBiggestF(reP, 2); fromUiBiggestF(imP, 0); break; case FRAC_MULTIBROT: case FRAC_MULTIJULIA: case FRAC_BURNINGSHIP: case FRAC_JULIABURNINGSHIP: case FRAC_MANDELBAR: case FRAC_JULIABAR: case FRAC_RUDY: if (readBiggestFloat(file, &reP) < 1) { FractalNow_read_werror(fileName); } if (readBiggestFloat(file, &imP) < 1) { FractalNow_read_werror(fileName); } break; default: FractalNow_werror("Unknown fractal formula \'%s\'.\n", tmp[0]); break; } cfromReImBiggestF(p, reP, imP); if (cmp_uiBiggestF(reP, 0) < 0 || cmp_uiBiggestF(reP, 100) > 0) { FractalNow_werror("Invalid fractal file : Re(p) must be between 0 and 100.\n"); } if (cmp_uiBiggestF(imP, 0) < 0 || cmp_uiBiggestF(imP, 100) > 0) { FractalNow_werror("Invalid fractal file : Im(p) must be between 0 and 100.\n"); } fromDoubleBiggestF(reC, 0.5); fromDoubleBiggestF(imC, 0.5); switch (fractalFormula) { case FRAC_MANDELBROT: case FRAC_BURNINGSHIP: case FRAC_MANDELBAR: case FRAC_MULTIBROT: break; case FRAC_JULIA: case FRAC_MULTIJULIA: case FRAC_JULIABURNINGSHIP: case FRAC_JULIABAR: case FRAC_RUDY: if (readBiggestFloat(file, &reC) < 1) { FractalNow_read_werror(fileName); } if (readBiggestFloat(file, &imC) < 1) { FractalNow_read_werror(fileName); } break; default: FractalNow_werror("Unknown fractal formula \'%s\'.\n", tmp[0]); break; } cfromReImBiggestF(c, reC, imC); if (readBiggestFloat(file, ¢erX) < 1) { FractalNow_read_werror(fileName); } if (readBiggestFloat(file, ¢erY) < 1) { FractalNow_read_werror(fileName); } if (readBiggestFloat(file, &spanX) < 1) { FractalNow_read_werror(fileName); } if (cmp_uiBiggestF(spanX, 0) <= 0) { FractalNow_werror("Invalid fractal file : spanX must be > 0.\n"); } if (readBiggestFloat(file, &spanY) < 1) { FractalNow_read_werror(fileName); } if (cmp_uiBiggestF(spanY, 0) <= 0) { FractalNow_werror("Invalid fractal file : spanY must be > 0.\n"); } double escapeRadius; if (readDouble(file, &escapeRadius) < 1) { FractalNow_read_werror(fileName); } if (escapeRadius <= 1.) { FractalNow_werror("Invalid config file : escape radius must be > 1.\n"); } uint32_t nbIterMax; if (readUint32(file, &nbIterMax) < 1) { FractalNow_read_werror(fileName); } InitFractalBiggestF(fractal, fractalFormula, p, c, centerX, centerY, spanX, spanY, escapeRadius, nbIterMax); end: cclearBiggestF(p); clearBiggestF(reP); clearBiggestF(imP); cclearBiggestF(c); clearBiggestF(reC); clearBiggestF(imC); clearBiggestF(centerX); clearBiggestF(centerY); clearBiggestF(spanX); clearBiggestF(spanY); return res; } ReadFractalFileFunction GetReadFractalFileFunction(const char *format) { if (strlen(format) != 4) { return NULL; } ReadFractalFileFunction readFractalFile = NULL; char formatStr[5]; strcpy(formatStr, format); toLowerCase(formatStr); uint_fast32_t i; for (i = 0; i < nbFractalFormats; ++i) { if (strcmp(formatStr, fractalFormatStr[i]) == 0) { readFractalFile = readFractalFileFunction[i]; break; } } return readFractalFile; } int isSupportedFractalFile(const char *fileName) { int res = 0; FILE *file; file=fopen(fileName,"r"); if (!file) { FractalNow_open_werror(fileName); } char formatStr[256]; if (readString(file, formatStr) < 1) { res = 1; } else { ReadFractalFileFunction readFractalFileFunction; readFractalFileFunction = GetReadFractalFileFunction(formatStr); res = (readFractalFileFunction == NULL); } end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } return !res; } int ReadFractalFileBody(Fractal *fractal, const char *fileName, FILE *file, const char *format) { FractalNow_message(stdout, T_VERBOSE, "Reading fractal file body...\n"); int res = 0; ReadFractalFileFunction readFractalFile = GetReadFractalFileFunction(format); if (readFractalFile == NULL) { FractalNow_werror("Unsupported fractal format '%s'.\n", format); } res |= readFractalFile(fractal, fileName, file); end: FractalNow_message(stdout, T_VERBOSE, "Reading fractal file body : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } int ReadFractalFile(Fractal *fractal, const char *fileName) { FractalNow_message(stdout, T_NORMAL, "Reading fractal file...\n"); int res = 0; FILE *file; file=fopen(fileName,"r"); if (!file) { FractalNow_open_werror(fileName); } char formatStr[256]; if (readString(file, formatStr) < 1) { FractalNow_read_werror(fileName); } res = ReadFractalFileBody(fractal, fileName, file, formatStr); end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } FractalNow_message(stdout, T_NORMAL, "Reading fractal file : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } WriteFractalFileFunction GetWriteFractalFileFunction(const char *format) { if (strlen(format) != 4) { return NULL; } WriteFractalFileFunction writeFractalFile = NULL; char formatStr[5]; strcpy(formatStr, format); toLowerCase(formatStr); uint_fast32_t i; for (i = 0; i < nbFractalFormats; ++i) { if (strcmp(formatStr, fractalFormatStr[i]) == 0) { writeFractalFile = writeFractalFileFunction[i]; break; } } return writeFractalFile; } int WriteFractalFileV075(const Fractal *fractal, const char *fileName, FILE *file) { int res = 0; BiggestFloat reP, imP; initBiggestF(reP); initBiggestF(imP); BiggestFloat reC, imC; initBiggestF(reC); initBiggestF(imC); const char *fractalFormula = fractalFormulaStr[(int)fractal->fractalFormula]; if (writeString(file, fractalFormula, "\n") < 0) { FractalNow_write_werror(fileName); } switch (fractal->fractalFormula) { case FRAC_MANDELBROT: case FRAC_JULIA: break; case FRAC_MULTIBROT: case FRAC_MULTIJULIA: case FRAC_BURNINGSHIP: case FRAC_JULIABURNINGSHIP: case FRAC_MANDELBAR: case FRAC_JULIABAR: case FRAC_RUDY: crealBiggestF(reP, fractal->p); if (writeBiggestFloat(file, reP, " ") < 0) { FractalNow_write_werror(fileName); } cimagBiggestF(imP, fractal->p); if (writeBiggestFloat(file, imP, "\n") < 0) { FractalNow_write_werror(fileName); } break; default: FractalNow_werror("Unknown fractal formula value '%d'.\n", fractal->fractalFormula); break; } switch (fractal->fractalFormula) { case FRAC_MANDELBROT: case FRAC_MULTIBROT: case FRAC_BURNINGSHIP: case FRAC_MANDELBAR: break; case FRAC_JULIA: case FRAC_MULTIJULIA: case FRAC_JULIABURNINGSHIP: case FRAC_JULIABAR: case FRAC_RUDY: crealBiggestF(reC, fractal->c); if (writeBiggestFloat(file, reC, " ") < 0) { FractalNow_write_werror(fileName); } cimagBiggestF(imC, fractal->c); if (writeBiggestFloat(file, imC, "\n") < 0) { FractalNow_write_werror(fileName); } break; default: FractalNow_werror("Unknown fractal formula value '%d'.\n", fractal->fractalFormula); break; } if (writeBiggestFloat(file, fractal->centerX, " ") < 0) { FractalNow_write_werror(fileName); } if (writeBiggestFloat(file, fractal->centerY, " ") < 0) { FractalNow_write_werror(fileName); } if (writeBiggestFloat(file, fractal->spanX, " ") < 0) { FractalNow_write_werror(fileName); } if (writeBiggestFloat(file, fractal->spanY, "\n") < 0) { FractalNow_write_werror(fileName); } if (writeDouble(file, fractal->escapeRadius, " ") < 0) { FractalNow_write_werror(fileName); } if (writeUint32(file, fractal->maxIter, "\n") < 0) { FractalNow_write_werror(fileName); } end: clearBiggestF(reP); clearBiggestF(imP); clearBiggestF(reC); clearBiggestF(imC); return res; } int WriteFractalFileBody(const Fractal *fractal, const char *fileName, FILE *file, const char *format) { FractalNow_message(stdout, T_VERBOSE, "Writing fractal file body...\n"); int res = 0; WriteFractalFileFunction writeFractalFile = GetWriteFractalFileFunction(format); if (writeFractalFile == NULL) { FractalNow_werror("Unsupported fractal format '%s'.\n", format); } res |= writeFractalFile(fractal, fileName, file); end: FractalNow_message(stdout, T_VERBOSE, "Writing fractal file body : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } int WriteFractalFile(const Fractal *fractal, const char *fileName) { FractalNow_message(stdout, T_NORMAL, "Writing fractal file...\n"); int res = 0; FILE *file; file=fopen(fileName,"w"); if (!file) { FractalNow_open_werror(fileName); } const char *format = fractalFormatStr[nbFractalFormats-1]; fprintf(file, "%s\n", format); res = WriteFractalFileBody(fractal, fileName, file, format); end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } FractalNow_message(stdout, T_NORMAL, "Writing fractal file : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } static inline Color aux_ComputeFractalColor(const Fractal *fractal, const RenderingParameters *render, const FractalEngine *engine, uint_fast32_t x, uint_fast32_t y, uint_fast32_t width, uint_fast32_t height, FractalCache *cache) { CacheEntry entry = RunFractalEngine(engine, fractal, render, x, y, width, height); double value = entry.value; Color res; if (cache != NULL) { AddToCacheThreadSafe(cache, entry); } else { FreeCacheEntry(entry); } if (value < 0) { res = render->spaceColor; } else { value = render->transferFunctionPtr(value)*render->realMultiplier+ render->realOffset; res = GetGradientColor(&render->gradient, (uint_fast64_t)(value)); } return res; } static inline Color aux_ComputeFractalImagePixel(const Fractal *fractal, const RenderingParameters *render, const FractalEngine *fractalEngine, uint_fast32_t x, uint_fast32_t y, uint_fast32_t width, uint_fast32_t height, FractalCache *cache) { /* We call auxiliary function because we don't need (and thus want) to * to re-get the FractalLoop to use for each pixel. It is already stored * in arg. */ return aux_ComputeFractalColor(fractal, render, fractalEngine, x, y, width, height, cache); } static inline Color ComputeFractalImagePixel(const DrawFractalArguments *arg, const FractalEngine *engine, uint_fast32_t width, uint_fast32_t height, uint_fast32_t x, uint_fast32_t y, int useCache, FractalCache *cache) { const Fractal *fractal = arg->fractal; const RenderingParameters *render = arg->render; Color res; if (useCache && cache != NULL) { ArrayValue aVal = GetArrayValue(cache, x, y); if (isArrayValueValid(aVal, cache)) { res = GetColorFromAVal(aVal, render); } else { res = aux_ComputeFractalImagePixel(fractal, render, engine, x, y, width, height, cache); } } else { res = aux_ComputeFractalImagePixel(fractal, render, engine, x, y, width, height, cache); } return res; } /* Compute (all) fractal values of given rectangle and render in image. */ static void aux1_DrawFractalThreadRoutine(ThreadArgHeader *threadArgHeader, const DrawFractalArguments *arg, const FractalEngine *engine) { Image *image = arg->image; uint_fast32_t nbRectangles = arg->nbRectangles; FractalCache *cache = arg->cache; UIRectangle *rectangle; uint_fast32_t rectHeight; int cancelRequested = CancelTaskRequested(threadArgHeader); uint_fast32_t counter = 0; for (uint_fast32_t i = 0; i < nbRectangles && !cancelRequested; ++i) { rectangle = &arg->rectangles[i]; rectHeight = rectangle->y2+1 - rectangle->y1; Color color; for (uint_fast32_t j=rectangle->y1; j<=rectangle->y2 && !cancelRequested; j++) { /* Updating progress after each line should be precise enough. */ SetThreadProgress(threadArgHeader, 100 * (i * rectHeight + (j-rectangle->y1)) / (rectHeight * nbRectangles)); for (uint_fast32_t k=rectangle->x1; k<=rectangle->x2 && !cancelRequested; k++) { HandleRequests(32); color = ComputeFractalImagePixel(arg, engine, image->width, image->height, k, j, 1, cache); PutPixelUnsafe(image,k,j,color); } } } SetThreadProgress(threadArgHeader, 100); } static inline int_fast8_t GetCornerIndex(const UIRectangle *rectangle, uint_fast32_t x, uint_fast32_t y) { if ((x == rectangle->x1 && y == rectangle->y1)) { return 0; } else if (x == rectangle->x2 && y == rectangle->y1) { return 1; } else if (x == rectangle->x1 && y == rectangle->y2) { return 2; } else if (x == rectangle->x2 && y == rectangle->y2) { return 3; } else { return -1; } } /* Compute fractal values of given rectangle into fractal_table, according to its dissimilarity and the given dissimilarity threshold (i.e. either computes it really, or interpolate linearly from the corners), and render in image. */ static inline void aux2_DrawFractalThreadRoutine(const DrawFractalArguments *arg, const FractalEngine *engine, const UIRectangle *rectangle) { Image *image = arg->image; uint_fast32_t width = image->width; uint_fast32_t height = image->height; double interpolationThreshold = arg->threshold; FractalCache *cache = arg->cache; Color corner[4]; if (rectangle->x1 == rectangle->x2 && rectangle->y1 == rectangle->y2) { /* Rectangle is just one pixel.*/ corner[0] = ComputeFractalImagePixel(arg,engine,width,height,rectangle->x1,rectangle->y1,1, cache); PutPixelUnsafe(image,rectangle->x1,rectangle->y1,corner[0]); return; } else if (rectangle->x1 == rectangle->x2) { /* Rectangle is a vertical line. There are only two "corners". */ corner[0] = ComputeFractalImagePixel(arg,engine,width,height,rectangle->x1,rectangle->y1,1, cache); corner[1] = corner[0]; corner[2] = ComputeFractalImagePixel(arg,engine,width,height,rectangle->x1,rectangle->y2,1, cache); corner[3] = corner[2]; /* Even for a line, we can still use quad interpolation.*/ } else if (rectangle->y1 == rectangle->y2) { /* Rectangle is a horizontal line. There are only two "corners". */ corner[0] = ComputeFractalImagePixel(arg,engine,width,height,rectangle->x1,rectangle->y1,1, cache); corner[1] = ComputeFractalImagePixel(arg,engine,width,height,rectangle->x2,rectangle->y1,1, cache); corner[2] = corner[0]; corner[3] = corner[1]; /* Even for a line, we can still use quad interpolation.*/ } else { /* "Real" rectangle. Compute four corners. */ corner[0] = ComputeFractalImagePixel(arg,engine,width,height,rectangle->x1,rectangle->y1,1, cache); corner[1] = ComputeFractalImagePixel(arg,engine,width,height,rectangle->x2,rectangle->y1,1, cache); corner[2] = ComputeFractalImagePixel(arg,engine,width,height,rectangle->x1,rectangle->y2,1, cache); corner[3] = ComputeFractalImagePixel(arg,engine,width,height,rectangle->x2,rectangle->y2,1 ,cache); } Color color; int_fast8_t index = -1; if (QuadAvgDissimilarity(corner) < interpolationThreshold) { /* Linear interpolation */ double sx = (double)rectangle->x2-rectangle->x1+1; double sy = (double)rectangle->y2-rectangle->y1+1; double x, y; for (uint_fast32_t i=rectangle->y1; i<=rectangle->y2; i++) { y = ((double)(i-rectangle->y1)) / sy; for (uint_fast32_t j=rectangle->x1; j<=rectangle->x2; j++) { index = GetCornerIndex(rectangle, j, i); if (index >= 0) { color = corner[index]; } else { x = ((double)(j-rectangle->x1)) / sx; color = QuadLinearInterpolation(corner,x,y); } PutPixelUnsafe(image,j,i,color); } } } else { /* Real computation */ for (uint_fast32_t i=rectangle->y1; i<=rectangle->y2; i++) { for (uint_fast32_t j=rectangle->x1; j<=rectangle->x2; j++) { index = GetCornerIndex(rectangle, j, i); if (index >= 0) { color = corner[index]; } else { color = ComputeFractalImagePixel(arg,engine,width,height,j,i,1, cache); } PutPixelUnsafe(image,j,i,color); } } } } void *DrawFractalThreadRoutine(void *arg) { ThreadArgHeader *threadArgHeader = GetThreadArgHeader(arg); DrawFractalArguments *c_arg = (DrawFractalArguments *)GetThreadArgBody(arg); FractalEngine engine; int res = CreateFractalEngine(&engine, c_arg->fractal, c_arg->render, c_arg->floatPrecision); if (res != 0) { return NULL; } if (c_arg->size == 1) { aux1_DrawFractalThreadRoutine(threadArgHeader, c_arg, &engine); } else { UIRectangle *currentRect; int cancelRequested = CancelTaskRequested(threadArgHeader); uint_fast32_t counter = 0; for (uint_fast32_t i = 0; i < c_arg->nbRectangles && !cancelRequested; ++i) { currentRect = &c_arg->rectangles[i]; /* Cut rectangle into smaller rectangles, so that all rectangles are smaller than quadInterpolationSize. */ UIRectangle *rectangle; uint_fast32_t nbRectangles; CutUIRectangleMaxSize(*currentRect, c_arg->size, &rectangle, &nbRectangles); /* If the rectangle dissimilarity is greater that threshold, we compute the fractal colors, otherwise we interpolate them using the corner colors. Check for cancellation after each rectangle is drawn. There should be very small latency because rectangles are fairly small (default size is 5*5 pixels). If this results in too much latency when cancelling, we might want to make this check in aux2_DrawFractalThreadRoutine, after each scanline for example. */ for (uint_fast32_t j = 0; j < nbRectangles && !cancelRequested; ++j) { /* Updating after each rectangle should be precise enough. */ SetThreadProgress(threadArgHeader, 100 * (i * nbRectangles + j) / (nbRectangles * c_arg->nbRectangles)); HandleRequests(0); aux2_DrawFractalThreadRoutine(c_arg, &engine, &rectangle[j]); } free(rectangle); } SetThreadProgress(threadArgHeader, 100); } FreeFractalEngine(&engine); int canceled = CancelTaskRequested(threadArgHeader); return (canceled ? PTHREAD_CANCELED : NULL); } char drawFractalMessage[] = "Drawing fractal"; Task *aux_CreateDrawFractalTask(Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t quadInterpolationSize, double interpolationThreshold, FloatPrecision floatPrecision, FractalCache *cache, uint_fast32_t nbThreads) { if (image->width < 2 || image->height < 2) { return DoNothingTask(); } if (quadInterpolationSize == 0) { quadInterpolationSize = 1; } uint_fast32_t nbPixels = image->width*image->height; uint_fast32_t nbThreadsNeeded = nbThreads; uint_fast32_t rectanglesPerThread = DEFAULT_RECTANGLES_PER_THREAD; if (nbPixels <= nbThreadsNeeded) { nbThreadsNeeded = nbPixels; rectanglesPerThread = 1; } else if (nbPixels < nbThreadsNeeded*rectanglesPerThread) { rectanglesPerThread = nbPixels / nbThreadsNeeded; } uint_fast32_t nbRectangles = nbThreadsNeeded*rectanglesPerThread; UIRectangle *rectangle; rectangle = (UIRectangle *)safeMalloc("rectangles", nbRectangles * sizeof(UIRectangle)); InitUIRectangle(&rectangle[0], 0, 0, image->width-1, image->height-1); if (CutUIRectangleInN(rectangle[0], nbRectangles, rectangle)) { FractalNow_error("Could not cut rectangle ((%"PRIuFAST32",%"PRIuFAST32"),\ (%"PRIuFAST32",%"PRIuFAST32") in %"PRIuFAST32" parts.\n", rectangle[0].x1, rectangle[0].y1, rectangle[0].x2, rectangle[0].y2, nbRectangles); } DrawFractalArguments *arg; arg = (DrawFractalArguments *)safeMalloc("arguments", nbThreadsNeeded * sizeof(DrawFractalArguments)); for (uint_fast32_t i = 0; i < nbThreadsNeeded; ++i) { arg[i].threadId = i; arg[i].cache = cache; arg[i].image = image; arg[i].copyImage = NULL; arg[i].fractal = fractal; arg[i].render = render; arg[i].floatPrecision = floatPrecision; arg[i].rectangles = &rectangle[i*rectanglesPerThread]; arg[i].nbRectangles = rectanglesPerThread; arg[i].size = quadInterpolationSize; arg[i].threshold = interpolationThreshold; } Task *task = CreateTask(drawFractalMessage, nbThreadsNeeded, arg, sizeof(DrawFractalArguments), DrawFractalThreadRoutine, FreeDrawFractalArguments); free(arg); return task; } inline Task *CreateDrawFractalTask(Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t quadInterpolationSize, double interpolationThreshold, FloatPrecision floatPrecision, FractalCache *cache, uint_fast32_t nbThreads) { Task *res; if (cache == NULL) { res = aux_CreateDrawFractalTask(image, fractal, render, quadInterpolationSize, interpolationThreshold, floatPrecision, cache, nbThreads); } else { /* Create preview image from cache first. */ Task *subTasks[2]; subTasks[0] = CreateFractalCachePreviewTask(image, cache, fractal, render, 1, nbThreads); subTasks[1] = aux_CreateDrawFractalTask(image, fractal, render, quadInterpolationSize, interpolationThreshold, floatPrecision, cache, nbThreads); res = CreateCompositeTask(NULL, 2, subTasks); } return res; } void DrawFractal(Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t quadInterpolationSize, double interpolationThreshold, FloatPrecision floatPrecision, FractalCache *cache, Threads *threads) { Task *task = CreateDrawFractalTask(image, fractal, render, quadInterpolationSize, interpolationThreshold, floatPrecision, cache, threads->N); int unused = ExecuteTaskBlocking(task, threads); UNUSED(unused); } void *AntiAliaseFractalThreadRoutine(void *arg) { ThreadArgHeader *threadArgHeader = GetThreadArgHeader(arg); DrawFractalArguments *c_arg = (DrawFractalArguments *)GetThreadArgBody(arg); Image *image = c_arg->image; const Image *copyImage = c_arg->copyImage; uint_fast32_t antialiasingSize = c_arg->size; double threshold = c_arg->threshold; FractalCache *cache = c_arg->cache; uint_fast32_t width = image->width; uint_fast32_t height = image->height; FractalEngine engine; int res = CreateFractalEngine(&engine, c_arg->fractal, c_arg->render, c_arg->floatPrecision); if (res != 0) { return NULL; } Image tmpImage1, tmpImage2; CreateImage(&tmpImage1, antialiasingSize, antialiasingSize, image->bytesPerComponent); CreateImage(&tmpImage2, 1, antialiasingSize, image->bytesPerComponent); Filter horizontalGaussianFilter; Filter verticalGaussianFilter; CreateHorizontalGaussianFilter2(&horizontalGaussianFilter, antialiasingSize); CreateVerticalGaussianFilter2(&verticalGaussianFilter, antialiasingSize); uint_fast32_t center = (antialiasingSize-1) / 2; uint_fast32_t bigWidth = width * antialiasingSize; uint_fast32_t bigHeight = height * antialiasingSize; Color C[9], c; double max = 0; UIRectangle *rectangle; uint_fast32_t counter = 0; int cancelRequested = CancelTaskRequested(threadArgHeader); for (uint_fast32_t i = 0; i < c_arg->nbRectangles && !cancelRequested; ++i) { rectangle = &c_arg->rectangles[i]; uint_fast32_t rectHeight = rectangle->y2+1 - rectangle->y1; uint_fast32_t y = rectangle->y1 * antialiasingSize; for (uint_fast32_t j = rectangle->y1; j <= rectangle->y2 && !cancelRequested; ++j, y+=antialiasingSize) { SetThreadProgress(threadArgHeader, 100 * (i * rectHeight + (j-rectangle->y1)) / (rectHeight * c_arg->nbRectangles)); uint_fast32_t x = rectangle->x1 * antialiasingSize; for (uint_fast32_t k = rectangle->x1; k <= rectangle->x2 && !cancelRequested; ++k, x+=antialiasingSize) { C[0] = iGetPixel(copyImage, k, j); C[1] = iGetPixel(copyImage, k-1, j-1); C[2] = iGetPixel(copyImage, k, j-1); C[3] = iGetPixel(copyImage, k+1, j-1); C[4] = iGetPixel(copyImage, k-1, j); C[5] = iGetPixel(copyImage, k+1, j); C[6] = iGetPixel(copyImage, k-1, j+1); C[7] = iGetPixel(copyImage, k, j+1); C[8] = iGetPixel(copyImage, k+1, j+1); max = 0; for (int_fast8_t l = 1; l < 9; ++l) { max = fmaxl(max, ColorManhattanDistance(C[0], C[l])); } if (max > threshold) { for (uint_fast32_t l=0; lwidth*antiAliasingSize < 2 || image->height*antiAliasingSize < 2) { return DoNothingTask(); } uint_fast32_t nbPixels = image->width*image->height; uint_fast32_t nbThreadsNeeded = nbThreads; uint_fast32_t rectanglesPerThread = DEFAULT_RECTANGLES_PER_THREAD; if (nbPixels <= nbThreadsNeeded) { nbThreadsNeeded = nbPixels; rectanglesPerThread = 1; } else if (nbPixels < nbThreadsNeeded*rectanglesPerThread) { rectanglesPerThread = nbPixels / nbThreadsNeeded; } uint_fast32_t nbRectangles = nbThreadsNeeded*rectanglesPerThread; UIRectangle *rectangle; rectangle = (UIRectangle *)safeMalloc("rectangles", nbRectangles * sizeof(UIRectangle)); InitUIRectangle(&rectangle[0], 0, 0, image->width-1, image->height-1); if (CutUIRectangleInN(rectangle[0], nbRectangles, rectangle)) { FractalNow_error("Could not cut rectangle ((%"PRIuFAST32",%"PRIuFAST32"),\ (%"PRIuFAST32",%"PRIuFAST32") in %"PRIuFAST32" parts.\n", rectangle[0].x1, rectangle[0].y1, rectangle[0].x2, rectangle[0].y2, nbRectangles); } DrawFractalArguments *arg; arg = (DrawFractalArguments *)safeMalloc("arguments", nbThreadsNeeded*sizeof(DrawFractalArguments)); Image *copyImage = (Image *)safeMalloc("copyImage", sizeof(Image)); *copyImage = CloneImage(image); for (uint_fast32_t i = 0; i < nbThreadsNeeded; ++i) { arg[i].threadId = i; /* No copy for image. * Concurrent read is OK. */ arg[i].image = image; arg[i].copyImage = copyImage; arg[i].cache = cache; /* Fractal is not copied because it is not modified.*/ arg[i].fractal = fractal; /* Rendering parameters are not modified.*/ arg[i].render = render; arg[i].floatPrecision = floatPrecision; arg[i].rectangles = &rectangle[i*rectanglesPerThread]; arg[i].nbRectangles = rectanglesPerThread; arg[i].size = antiAliasingSize; arg[i].threshold = threshold; } Task *res = CreateTask(antiAliaseFractalMessage, nbThreadsNeeded, arg, sizeof(DrawFractalArguments), AntiAliaseFractalThreadRoutine, FreeDrawFractalArguments); free(arg); return res; } void AntiAliaseFractal(Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t antiAliasingSize, double threshold, FloatPrecision floatPrecision, FractalCache *cache, Threads *threads) { Task *task = CreateAntiAliaseFractalTask(image, fractal, render, antiAliasingSize, threshold, floatPrecision, cache, threads->N); int unused = ExecuteTaskBlocking(task, threads); UNUSED(unused); } void FreeFractal(Fractal fractal) { /* Because depending on BiggestFloat type, nothing could be done here. */ UNUSED(fractal); cclearBiggestF(fractal.p); cclearBiggestF(fractal.c); clearBiggestF(fractal.centerX); clearBiggestF(fractal.centerY); clearBiggestF(fractal.spanX); clearBiggestF(fractal.spanY); clearBiggestF(fractal.x1); clearBiggestF(fractal.y1); } fractalnow-0.8.2/lib/src/filter.c000664 001750 001750 00000022431 13175112471 016577 0ustar00mpegmpeg000000 000000 /* * filter.c -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "filter.h" #include "misc.h" #include "uirectangle.h" #include #include #include #define HandleRequests(max_counter) \ if (counter == max_counter) {\ HandlePauseRequest(threadArgHeader);\ cancelRequested =\ CancelTaskRequested(threadArgHeader);\ counter = 0;\ } else {\ ++counter;\ } typedef struct s_ApplyFilterArguments { uint_fast32_t threadId; Image *dst; uint_fast32_t nbRectangles; UIRectangle *rectangles; const Image *src; Filter *filter; } ApplyFilterArguments; void FreeApplyFilterArguments(void *arg) { ApplyFilterArguments *c_arg = (ApplyFilterArguments *)arg; if (c_arg->threadId == 0) { free(c_arg->rectangles); FreeFilter(*c_arg->filter); free(c_arg->filter); } } void InitFilter(Filter *filter, uint_fast32_t sx, uint_fast32_t sy, uint_fast32_t cx, uint_fast32_t cy, double *data) { filter->sx = sx; filter->sy = sy; filter->cx = cx; filter->cy = cy; filter->data = data; } void InitFilter2(Filter *filter, uint_fast32_t sx, uint_fast32_t sy, double *data) { filter->sx = sx; filter->sy = sy; filter->cx = (sx-1) / 2; filter->cy = (sy-1) / 2; filter->data = data; } Filter CopyFilter(const Filter *filter) { Filter res; double *data = (double *)safeMalloc("filter data", filter->sx*filter->sy*sizeof(double)); memcpy(data, filter->data, filter->sx*filter->sy*sizeof(double)); InitFilter(&res, filter->sx, filter->sy, filter->cx, filter->cy, data); return res; } void CreateHorizontalGaussianFilter(Filter *filter, double sigma) { if (sigma <= 0) { FractalNow_error("Sigma must be > 0.\n"); } uint_fast32_t radius = floor(3. * sigma); filter->sx = radius*2+1; filter->sy = 1; filter->cx = radius; filter->cy = 0; filter->data = (double *)safeMalloc("filter", filter->sx*filter->sy*sizeof(double)); double sigma2_x_2 = sigma*sigma*2; double *value = filter->data; int_fast64_t size = (int_fast64_t)filter->cx; double sum = 0; for (int_fast64_t i = -size; i <= size; ++i) { *value = exp(-i*i/sigma2_x_2); sum += *(value++); } if (sum != 0.) { MultiplyFilterByScalar(filter, 1./sum); } } inline void CreateHorizontalGaussianFilter2(Filter *filter, double radius) { if (radius <= 0) { FractalNow_error("Radius must be > 0.\n"); } CreateHorizontalGaussianFilter(filter, radius / 3.); } void CreateVerticalGaussianFilter(Filter *filter, double sigma) { if (sigma <= 0) { FractalNow_error("Sigma must be > 0.\n"); } uint_fast32_t radius = floor(3. * sigma); filter->sx = 1; filter->sy = radius*2+1; filter->cx = 0; filter->cy = radius; filter->data = (double *)safeMalloc("filter", filter->sx*filter->sy*sizeof(double)); double sigma2_x_2 = sigma*sigma*2; double *value = filter->data; int_fast64_t size = (int_fast64_t)filter->cy; double sum = 0; for (int_fast64_t i = -size; i <= size; ++i) { *value = exp(-i*i/sigma2_x_2); sum += *(value++); } if (sum != 0.) { MultiplyFilterByScalar(filter, 1./sum); } } inline void CreateVerticalGaussianFilter2(Filter *filter, double radius) { if (radius <= 0) { FractalNow_error("Radius must be > 0.\n"); } CreateVerticalGaussianFilter(filter, radius / 3.); } void CreateGaussianFilter(Filter *filter, double sigma) { if (sigma <= 0) { FractalNow_error("Sigma must be > 0.\n"); } uint_fast32_t radius = floor(3. * sigma); filter->sx = radius*2+1; filter->sy = radius*2+1; filter->cx = radius; filter->cy = radius; filter->data = (double *)safeMalloc("filter", filter->sx*filter->sy*sizeof(double)); double sigma2_x_2 = sigma*sigma*2; double *value = filter->data; int_fast64_t size = (int_fast64_t)filter->cx; double sum = 0; for (int_fast64_t i = -size; i <= size; ++i) { for (int_fast64_t j = -size; j <= size; ++j) { *value = exp(-(i*i+j*j)/sigma2_x_2); sum += *(value++); } } if (sum != 0.) { MultiplyFilterByScalar(filter, 1./sum); } } void CreateGaussianFilter2(Filter *filter, double radius) { if (radius <= 0) { FractalNow_error("Radius must be > 0.\n"); } CreateGaussianFilter(filter, radius / 3.); } inline double GetFilterValueUnsafe(const Filter *filter, uint_fast32_t x, uint_fast32_t y) { return filter->data[x+y*filter->sx]; } void MultiplyFilterByScalar(Filter *filter, double scalar) { double *value = filter->data; for (uint_fast32_t i = 0; i < filter->sx; ++i) { for (uint_fast32_t j = 0; j < filter->sy; ++j) { *(value++) *= scalar; } } } int NormalizeFilter(Filter *filter) { double *value = filter->data; double sum = 0; for (uint_fast32_t i = 0; i < filter->sx; ++i) { for (uint_fast32_t j = 0; j < filter->sy; ++j) { sum += *(value++); } } if (sum != 0.) { // Otherwize do nothing : can't be normalized anyway MultiplyFilterByScalar(filter, 1./sum); return 0; } else { return 1; } } Color ApplyFilterOnSinglePixel(const Image *src, uint_fast32_t x, uint_fast32_t y, const Filter *filter) { double value; Color color; double r, g, b; r = 0; g = 0; b = 0; for (uint_fast32_t i = 0; i < filter->sx; ++i) { for (uint_fast32_t j = 0; j < filter->sy; ++j) { color = iGetPixel(src, x-filter->cx+i, y-filter->cy+j); value = GetFilterValueUnsafe(filter, i, j); r += color.r * value; g += color.g * value; b += color.b * value; } } color.bytesPerComponent = src->bytesPerComponent; color.r = r; color.g = g; color.b = b; return color; } void *ApplyFilterThreadRoutine(void *arg) { ThreadArgHeader *threadArgHeader = GetThreadArgHeader(arg); ApplyFilterArguments *c_arg = (ApplyFilterArguments *)GetThreadArgBody(arg); Image *dst = c_arg->dst; const Image *src = c_arg->src; Filter *filter = c_arg->filter; uint_fast32_t nbRectangles = c_arg->nbRectangles; UIRectangle *dstRect; uint_fast32_t rectHeight; uint_fast32_t counter = 0; int cancelRequested = CancelTaskRequested(threadArgHeader); for (uint_fast32_t i = 0; i < nbRectangles && !cancelRequested; ++i) { dstRect = &c_arg->rectangles[i]; rectHeight = dstRect->y2+1 - dstRect->y1; for (uint_fast32_t j = dstRect->y1; j <= dstRect->y2 && !cancelRequested; ++j) { SetThreadProgress(threadArgHeader, 100 * (i * rectHeight + (j-dstRect->y1)) / (rectHeight * nbRectangles)); for (uint_fast32_t k = dstRect->x1; k <= dstRect->x2 && !cancelRequested; ++k) { HandleRequests(32); PutPixelUnsafe(dst, k, j, ApplyFilterOnSinglePixel(src, k, j, filter)); } } } SetThreadProgress(threadArgHeader, 100); int canceled = CancelTaskRequested(threadArgHeader); return (canceled ? PTHREAD_CANCELED : NULL); } char applyFilterMessage[] = "Applying filter"; Task *CreateApplyFilterTask(Image *dst, const Image *src, const Filter *filter, uint_fast32_t nbThreads) { if (src->width == 0 || src->height == 0) { return DoNothingTask(); } uint_fast32_t nbPixels = src->width*src->height; uint_fast32_t nbThreadsNeeded = nbThreads; uint_fast32_t rectanglesPerThread = DEFAULT_RECTANGLES_PER_THREAD; if (nbPixels <= nbThreadsNeeded) { nbThreadsNeeded = nbPixels; rectanglesPerThread = 1; } else if (nbPixels < nbThreadsNeeded*rectanglesPerThread) { rectanglesPerThread = nbPixels / nbThreadsNeeded; } uint_fast32_t nbRectangles = nbThreadsNeeded*rectanglesPerThread; UIRectangle *rectangle; rectangle = (UIRectangle *)safeMalloc("rectangles", nbRectangles * sizeof(UIRectangle)); InitUIRectangle(&rectangle[0], 0, 0, dst->width-1, dst->height-1); if (CutUIRectangleInN(rectangle[0], nbRectangles, rectangle)) { FractalNow_error("Could not cut rectangle ((%"PRIuFAST32",%"PRIuFAST32"),\ (%"PRIuFAST32",%"PRIuFAST32") in %"PRIuFAST32" parts.\n", rectangle[0].x1, rectangle[0].y1, rectangle[0].x2, rectangle[0].y2, nbRectangles); } ApplyFilterArguments *arg; arg = (ApplyFilterArguments *)safeMalloc("arguments", nbThreadsNeeded * sizeof(ApplyFilterArguments)); Filter *copyFilter = (Filter *)safeMalloc("copy filter", sizeof(Filter)); *copyFilter = CopyFilter(filter); for (uint_fast32_t i = 0; i < nbThreadsNeeded; ++i) { arg[i].threadId = i; arg[i].dst = dst; arg[i].nbRectangles = rectanglesPerThread; arg[i].rectangles = &rectangle[i*rectanglesPerThread]; arg[i].src = src; arg[i].filter = copyFilter; } Task *res = CreateTask(applyFilterMessage, nbThreadsNeeded, arg, sizeof(ApplyFilterArguments), ApplyFilterThreadRoutine, FreeApplyFilterArguments); free(arg); return res; } void ApplyFilter(Image *dst, const Image *src, const Filter *filter, Threads *threads) { Task *task = CreateApplyFilterTask(dst, src, filter, threads->N); int unused = ExecuteTaskBlocking(task, threads); UNUSED(unused); } void FreeFilter(Filter filter) { free(filter.data); } fractalnow-0.8.2/examples/config_files/config05.config000664 001750 001750 00000000313 13175112471 022652 0ustar00mpegmpeg000000 000000 c075 mandelbrot -0.743643925055 0.131825905901 5.08373779904306E-08 5.08373779904306E-08 64 7500 1 0x0 iterationcount smooth squareroot 0.035 0 0 0x389f 0.25 0xffffff 0.5 0xfffd42 0.75 0xbe0700 1 0x389f fractalnow-0.8.2/gui/src/export_fractal_image_dialog.cpp000664 001750 001750 00000034755 13175124223 023400 0ustar00mpegmpeg000000 000000 /* * export_fractal_image_dialog.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "export_fractal_image_dialog.h" #include "task_progress_dialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ExportFractalImageDialog::ExportFractalImageDialog(const FractalConfig &config, uint_fast32_t nbThreads, QString imageDir, QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f), config(CopyFractalConfig(&config)), fractal(this->config.fractal), render(this->config.render) { this->floatPrecision = FP_DOUBLE; this->imageDir = imageDir; if (this->imageDir.isEmpty()) { this->imageDir = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); } setWindowTitle(tr("Export image")); QVBoxLayout *vBoxLayout = new QVBoxLayout; /* Image parameters (width, height, depth) .*/ QGroupBox *imageParamBox = new QGroupBox(tr("&Image parameters"), this); QHBoxLayout *hBoxLayout1 = new QHBoxLayout; QFormLayout *formLayout = new QFormLayout; imageWidthBox = new QSpinBox(this); imageWidthBox->setRange(2, 20000); imageWidthBox->setValue(1280); imageHeightBox = new QSpinBox(this); imageHeightBox->setRange(2, 20000); imageHeightBox->setValue(1024); colorDepthBox = new QComboBox(this); colorDepthBox->addItem(tr("8 bits")); colorDepthBox->addItem(tr("16 bits")); colorDepthBox->setCurrentIndex(0); formLayout->addRow(tr("Width:"), imageWidthBox); formLayout->addRow(tr("Height:"), imageHeightBox); formLayout->addRow(tr("Color depth:"), colorDepthBox); hBoxLayout1->addLayout(formLayout); hBoxLayout1->addStretch(1); imageParamBox->setLayout(hBoxLayout1); /* Anti-aliasing methods */ QGroupBox *antiAliasingBox = new QGroupBox(tr("&Anti-aliasing method"), this); QGridLayout *gridLayout = new QGridLayout; noAAMButton = new QRadioButton(tr("&None")); connect(noAAMButton, SIGNAL(toggled(bool)), this, SLOT(onAAMNoneToggled(bool))); gaussianBlurAAMButton = new QRadioButton(tr("Gaussian &blur")); connect(gaussianBlurAAMButton, SIGNAL(toggled(bool)), this, SLOT(onAAMBlurToggled(bool))); QLabel *blurRadiusLabel = new QLabel(tr("Radius:")); blurRadiusBox = new QDoubleSpinBox; blurRadiusBox->setRange(0.5, 5); blurRadiusBox->setValue(2); adaptiveAAMButton = new QRadioButton(tr("&Adaptive")); connect(adaptiveAAMButton, SIGNAL(toggled(bool)), this, SLOT(onAAMAdaptiveToggled(bool))); QLabel *adaptiveSizeLabel = new QLabel(tr("Size:")); adaptiveSizeBox = new QSpinBox; adaptiveSizeBox->setRange(2, 7); adaptiveSizeBox->setValue(3); oversamplingAAMButton = new QRadioButton(tr("&Oversampling")); connect(oversamplingAAMButton, SIGNAL(toggled(bool)), this, SLOT(onAAMOversamplingToggled(bool))); QLabel *oversamplingSizeLabel = new QLabel(tr("Size:")); oversamplingSizeBox = new QDoubleSpinBox; oversamplingSizeBox->setRange(1.5, 7); oversamplingSizeBox->setValue(5); adaptiveAAMButton->setChecked(true); gridLayout->addWidget(noAAMButton, 0, 0); gridLayout->addWidget(gaussianBlurAAMButton, 1, 0); gridLayout->addWidget(blurRadiusLabel, 2, 1); gridLayout->addWidget(blurRadiusBox, 2, 2); gridLayout->addWidget(adaptiveAAMButton, 3, 0); gridLayout->addWidget(adaptiveSizeLabel, 4, 1); gridLayout->addWidget(adaptiveSizeBox, 4, 2); gridLayout->addWidget(oversamplingAAMButton, 5, 0); gridLayout->addWidget(oversamplingSizeLabel, 6, 1); gridLayout->addWidget(oversamplingSizeBox, 6, 2); gridLayout->setColumnStretch(3, 1); gridLayout->setRowStretch(7, 1); antiAliasingBox->setLayout(gridLayout); /* Set dialog main layouts. */ QHBoxLayout *hBoxLayout2 = new QHBoxLayout; hBoxLayout2->addWidget(antiAliasingBox); hBoxLayout2->addSpacing(20); hBoxLayout2->addWidget(imageParamBox); dialogButtonBox = new QDialogButtonBox(this); cancelButton = dialogButtonBox->addButton(QDialogButtonBox::Cancel); connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); exportButton = dialogButtonBox->addButton(tr("Export"), QDialogButtonBox::AcceptRole); connect(exportButton, SIGNAL(clicked()), this, SLOT(exportImage())); vBoxLayout->addLayout(hBoxLayout2); vBoxLayout->addWidget(dialogButtonBox); setLayout(vBoxLayout); threads = CreateThreads(nbThreads); } ExportFractalImageDialog::~ExportFractalImageDialog() { DestroyThreads(threads); FreeFractalConfig(config); } void ExportFractalImageDialog::resetFractalConfig(const FractalConfig &config) { FractalConfig newConfig = CopyFractalConfig(&config); FreeFractalConfig(this->config); this->config = newConfig; } void ExportFractalImageDialog::setFloatPrecision(FloatPrecision floatPrecision) { this->floatPrecision = floatPrecision; } QString ExportFractalImageDialog::exportedFile() { return m_exportedFile; } void ExportFractalImageDialog::onAAMNoneToggled(bool checked) { if (checked) { blurRadiusBox->setEnabled(false); adaptiveSizeBox->setEnabled(false); oversamplingSizeBox->setEnabled(false); } } void ExportFractalImageDialog::onAAMBlurToggled(bool checked) { if (checked) { blurRadiusBox->setEnabled(true); adaptiveSizeBox->setEnabled(false); oversamplingSizeBox->setEnabled(false); } } void ExportFractalImageDialog::onAAMAdaptiveToggled(bool checked) { if (checked) { blurRadiusBox->setEnabled(false); adaptiveSizeBox->setEnabled(true); oversamplingSizeBox->setEnabled(false); } } void ExportFractalImageDialog::onAAMOversamplingToggled(bool checked) { if (checked) { blurRadiusBox->setEnabled(false); adaptiveSizeBox->setEnabled(false); oversamplingSizeBox->setEnabled(true); } } ExportFractalImageDialog::AntiAliasingMethod ExportFractalImageDialog::getAntiAliasingMethod() const { if (noAAMButton->isChecked()) { return AAM_NONE; } else if (gaussianBlurAAMButton->isChecked()) { return AAM_GAUSSIANBLUR; } else if (oversamplingAAMButton->isChecked()) { return AAM_OVERSAMPLING; } else { return AAM_ADAPTIVE; } } void ExportFractalImageDialog::exportImage() { int depth = colorDepthBox->currentIndex() + 1; QString imageFormats = (depth == 1) ? "(*.png *.jpg *.tiff *.ppm)" : "(*.ppm)"; QString imageSuffix = (depth == 1) ? ".png" : ".ppm"; QString fileName = QFileDialog::getSaveFileName(this, tr("Export image"), imageDir + "/fractal" + imageSuffix, tr("Images ") + imageFormats); /* It is not very clear in Qt documentation, * but I think a file dialog cannot return * an empty string if user clicks OK. * (one thing for sure is that it returns a * null string when user clicks Cancel) */ if (fileName.isEmpty()) { return; } QFileInfo fileInfo(fileName); QString imageFormat; RenderingParameters render = CopyRenderingParameters(&this->render); if (depth == 2) { /* Check that extension is PPM (only format supported for 16 bits).*/ if (fileInfo.suffix().compare(QString("PPM"), Qt::CaseInsensitive)) { QMessageBox::warning(this, tr("File name extension is not PPM"), tr("16-bits image will be exported as PPM, ignoring file extension.")); } Gradient gradient16 = Gradient16(&render.gradient); ResetGradient(&render, gradient16); FreeGradient(gradient16); } else { /* Get image format from extension (suffix). */ QString allowedFormats[] = {"PNG","JPG","JPEG","TIFF","PPM"}; int nbAllowedFormats = sizeof(allowedFormats) / sizeof(QString); int i; for (i = 0; i < nbAllowedFormats; ++i) { if (!fileInfo.suffix().compare(allowedFormats[i], Qt::CaseInsensitive)) { imageFormat = allowedFormats[i]; break; } } if (i == nbAllowedFormats) { imageFormat = allowedFormats[0]; QMessageBox::warning(this, tr("Unknown image format"), tr("Could not guess image format from file name extension. Image " "will be exported as PNG.")); } } mpfr_t spanX, spanY; mpfr_init(spanX); mpfr_init(spanY); /* Adjust spanX & spanY to image width and height (keep ratio). */ int width = imageWidthBox->value(); int height = imageHeightBox->value(); if (height / (double)width < 1) { mpfr_mul_ui(spanX, fractal.spanY, width, MPFR_RNDN); mpfr_div_ui(spanX, spanX, height, MPFR_RNDN); mpfr_set(spanY, fractal.spanY, MPFR_RNDN); } else { mpfr_set(spanX, fractal.spanX, MPFR_RNDN); mpfr_mul_ui(spanY, fractal.spanX, height, MPFR_RNDN); mpfr_div_ui(spanY, spanY, width, MPFR_RNDN); } Fractal fractal; InitFractal2(&fractal, this->fractal.fractalFormula, this->fractal.p, this->fractal.c, this->fractal.centerX, this->fractal.centerY, spanX, spanY, this->fractal.escapeRadius, this->fractal.maxIter); mpfr_clear(spanX); mpfr_clear(spanY); /* Now generate fractal image according to anti-aliasing method. */ Image fractalImg, tmpImg; CreateImage(&fractalImg, width, height, render.bytesPerComponent); Task *task; int canceled = 0; switch (getAntiAliasingMethod()) { case AAM_NONE: { task = CreateDrawFractalTask(&fractalImg, &fractal, &render, DEFAULT_QUAD_INTERPOLATION_SIZE, DEFAULT_COLOR_DISSIMILARITY_THRESHOLD, floatPrecision, NULL, threads->N); LaunchTask(task, threads); canceled = TaskProgressDialog::progress(task, tr("Drawing fractal..."), tr("Abort"), this); break; } case AAM_GAUSSIANBLUR: CreateImage(&tmpImg, width, height, render.bytesPerComponent); task = CreateDrawFractalTask(&fractalImg, &fractal, &render, DEFAULT_QUAD_INTERPOLATION_SIZE, DEFAULT_COLOR_DISSIMILARITY_THRESHOLD, floatPrecision, NULL, threads->N); LaunchTask(task, threads); canceled = TaskProgressDialog::progress(task, tr("Drawing fractal..."), tr("Abort"), this); if (!canceled) { FreeTask(task); task = CreateApplyGaussianBlurTask(&fractalImg, &tmpImg, &fractalImg, blurRadiusBox->value(), threads->N); LaunchTask(task, threads); canceled = TaskProgressDialog::progress(task, tr("Applying blur..."), tr("Abort"), this); } FreeImage(tmpImg); break; case AAM_OVERSAMPLING: CreateImage(&tmpImg, width*oversamplingSizeBox->value(), height*oversamplingSizeBox->value(), render.bytesPerComponent); task = CreateDrawFractalTask(&tmpImg, &fractal, &render, DEFAULT_QUAD_INTERPOLATION_SIZE, DEFAULT_COLOR_DISSIMILARITY_THRESHOLD, floatPrecision, NULL, threads->N); LaunchTask(task, threads); canceled = TaskProgressDialog::progress(task, tr("Drawing fractal..."), tr("Abort"), this); if (!canceled) { FreeTask(task); task = CreateDownscaleImageTask(&fractalImg, &tmpImg, threads->N); LaunchTask(task, threads); canceled = TaskProgressDialog::progress(task, tr("Downscaling image..."), tr("Abort"), this); } FreeImage(tmpImg); break; case AAM_ADAPTIVE: task = CreateDrawFractalTask(&fractalImg, &fractal, &render, DEFAULT_QUAD_INTERPOLATION_SIZE, DEFAULT_COLOR_DISSIMILARITY_THRESHOLD, floatPrecision, NULL, threads->N); LaunchTask(task, threads); canceled = TaskProgressDialog::progress(task, tr("Drawing fractal..."), tr("Abort"), this); if (!canceled) { FreeTask(task); task = CreateAntiAliaseFractalTask(&fractalImg, &fractal, &render, adaptiveSizeBox->value(), DEFAULT_ADAPTIVE_AAM_THRESHOLD, floatPrecision, NULL, threads->N); LaunchTask(task, threads); canceled = TaskProgressDialog::progress(task, tr("Anti-aliasing fractal..."), tr("Abort"), this); } break; default: FractalNow_error("Unknown anti-aliasing method.\n"); break; } FreeTask(task); if (canceled) { FreeImage(fractalImg); } else { setEnabled(false); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); QApplication::processEvents(); /* Export image. */ int exportError = 0; if (depth == 2) { if ((exportError = ExportPPM(fileName.toStdString().c_str(), &fractalImg)) != 0) { QMessageBox::critical(this, tr("Failed to export image"), tr("Error occured while exporting image.")); } } else { QImage qImage(fractalImg.data, fractalImg.width, fractalImg.height, QImage::Format_RGB32); qImage.setText("Description", tr("Fractal image generated by ") + QApplication::applicationName()); qImage.setText("Fractal formula", fractalFormulaDescStr[(int)fractal.fractalFormula]); char *rePStr, *imPStr, *reCStr, *imCStr; char *centerXStr, *centerYStr, *spanXStr, *spanYStr; mpfr_asprintf(&rePStr, "%Rf", mpc_realref(fractal.p)); mpfr_asprintf(&imPStr, "%Rf", mpc_imagref(fractal.p)); mpfr_asprintf(&reCStr, "%Rf", mpc_realref(fractal.c)); mpfr_asprintf(&imCStr, "%Rf", mpc_imagref(fractal.c)); mpfr_asprintf(¢erXStr, "%Rf", fractal.centerX); mpfr_asprintf(¢erYStr, "%Rf", fractal.centerY); mpfr_asprintf(&spanXStr, "%Rf", fractal.spanX); mpfr_asprintf(&spanYStr, "%Rf", fractal.spanY); qImage.setText("Fractal p", QString(rePStr) + " + i*" + QString(imPStr)); qImage.setText("Fractal c", QString(reCStr) + " + i*" + QString(imCStr)); qImage.setText("Fractal center", "(" + QString(centerXStr) + ", " + QString(centerYStr) + ")"); qImage.setText("Fractal span X", QString(spanXStr)); qImage.setText("Fractal span Y", QString(spanYStr)); qImage.setText("Fractal bailout radius", QString::number(fractal.escapeRadius, 'G', LDBL_DIG)); qImage.setText("Fractal max iterations", QString::number(fractal.maxIter)); if ((exportError = !qImage.save(fileName, imageFormat.toStdString().c_str())) != 0) { QMessageBox::critical(this, tr("Failed to export image"), tr("Error occured while exporting image.")); } mpfr_free_str(rePStr); mpfr_free_str(imPStr); mpfr_free_str(reCStr); mpfr_free_str(imCStr); mpfr_free_str(centerXStr); mpfr_free_str(centerYStr); mpfr_free_str(spanXStr); mpfr_free_str(spanYStr); } FreeImage(fractalImg); setEnabled(true); QApplication::restoreOverrideCursor(); if (!exportError) { m_exportedFile = fileName; this->accept(); } } FreeFractal(fractal); FreeRenderingParameters(render); } fractalnow-0.8.2/lib/include/fractal.h000664 001750 001750 00000035314 13175115345 017576 0ustar00mpegmpeg000000 000000 /* * fractal.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal.h * \brief Main header file related to fractals. * * A fractal point is computed and colored as follows : * - The fractal loop function is executed, and returns a floating point * value. * \see fractal_loop.h * - The transfer function is applied, as well as the multiplier, and the * offset is added. * - Finally, the value is mapped to a color using the gradient. * * Note that points that belong to the fractal set (radius <= escape radius * after the maximum number of iterations) do not go through all those * steps : the fractal loop gives a negative value, so that the color of * fractal space is returned. * * \author Marc Pegon */ #ifndef __FRACTAL_H__ #define __FRACTAL_H__ #include "float_precision.h" #include "complex_wrapper.h" #include "gradient.h" #include "image.h" #include "fractal_cache.h" #include "fractal_formula.h" #include "fractal_rendering_parameters.h" #include "task.h" #include "thread.h" #include #ifdef __cplusplus extern "C" { #endif /** * \def DEFAULT_QUAD_INTERPOLATION_SIZE * \brief Default maximum size of quadrilaterals for interpolation. * * \see DrawFractalFast for more details. */ #define DEFAULT_QUAD_INTERPOLATION_SIZE (uint_fast32_t)(5) /** * \def DEFAULT_COLOR_DISSIMILARITY_THRESHOLD * \brief Default color dissimilarity threshold for quad interpolation. * * \see DrawFractalFast for more details. */ #define DEFAULT_COLOR_DISSIMILARITY_THRESHOLD (double)(3.5E-3) /** * \def DEFAULT_ADAPTIVE_AAM_THRESHOLD * \brief Default threshold for adaptive anti-aliasing. * * \see AntiAliaseFractal for more details. */ #define DEFAULT_ADAPTIVE_AAM_THRESHOLD (double)(5.05E-2) /** * \struct Fractal * \brief Description of a subset of some fractal set. */ /** * \typedef Fractal * \brief Convenient typedef for struct Fractal. */ typedef struct Fractal { FractalFormula fractalFormula; /*!< Fractal formula.*/ BiggestComplexFloat p; /*!< Parameter for some fractals (main power in iteration z = z^p + ...).*/ BiggestComplexFloat c; /*!< Parameter for Julia and Rudy fractal.*/ BiggestFloat centerX; /*!< X coordinate of the center of the fractal subset.*/ BiggestFloat centerY; /*!< Y coordinate of the center of the fractal subset.*/ BiggestFloat spanX; /*!< X span of the fractal subset.*/ BiggestFloat spanY; /*!< Y span of the fractal subset.*/ double escapeRadius; /*!< Escape radius for computing fractal.*/ uint_fast32_t maxIter; /*!< Maximum number of iterations for computing fractal.*/ /* Some parameters for internal use.*/ BiggestFloat x1; /*!< X coordinate of the upper left point of the fractal subset.*/ BiggestFloat y1; /*!< Y coordinate of the upper left point of the fractal subset.*/ } Fractal; /** * \fn void InitFractal(Fractal *fractal, FractalFormula fractalFormula, Complex_l p, Complex_l complex c, long double centerX, long double centerY, long double spanX, long double spanY, double escapeRadius, uint_fast32_t maxIter) * \brief Initialize fractal structure. * * \param fractal Pointer to fractal structure to initialize. * \param fractalFormula Fractal type. * \param p (main power in iteration) parameter for fractal. * \param c Parameter for Julia fractal (will be ignored for Mandelbrot fractal). * \param centerX X coordinate of the center of the fractal subset. * \param centerY Y coordinate of the center of the fractal subset. * \param spanX * \param spanY * \param escapeRadius Escape radius for computing fractal. * \param maxIter Maximum number of iterations for computing fractal. */ void InitFractal(Fractal *fractal, FractalFormula fractalFormula, Complex_l p, Complex_l c, long double centerX, long double centerY, long double spanX, long double spanY, double escapeRadius, uint_fast32_t maxIter); #ifdef _ENABLE_MP_FLOATS /** * \fn void InitFractal2(Fractal *fractal, FractalFormula fractalFormula, const mpc_t p, const mpc_t c, const mpfr_t centerX, const mpfr_t centerY, const mpfr_t spanX, const mpfr_t spanY, double escapeRadius, uint_fast32_t maxIter) * \brief Initialize fractal structure. * * \param fractal Pointer to fractal structure to initialize. * \param fractalFormula Fractal type. * \param p (main power in iteration) parameter for fractal. * \param c Parameter for Julia fractal (will be ignored for Mandelbrot fractal). * \param centerX X coordinate of the center of the fractal subset. * \param centerY Y coordinate of the center of the fractal subset. * \param spanX * \param spanY * \param escapeRadius Escape radius for computing fractal. * \param maxIter Maximum number of iterations for computing fractal. */ void InitFractal2(Fractal *fractal, FractalFormula fractalFormula, const mpc_t p, const mpc_t c, const mpfr_t centerX, const mpfr_t centerY, const mpfr_t spanX, const mpfr_t spanY, double escapeRadius, uint_fast32_t maxIter); #endif /** * \fn Fractal CopyFractal(const Fractal *fractal) * \brief Copy fractal. * * \param fractal Pointer to fractal to copy. * \return Copy of fractal. */ Fractal CopyFractal(const Fractal *fractal); /** * \fn int isSupportedFractalFile(const char *fileName) * \brief Check whether a file is a supported fractal file. * * \param fileName File name. * \return 1 if file is a supported fractal file, 0 otherwise. */ int isSupportedFractalFile(const char *fileName); /** * \fn int ReadFractalFileBody(Fractal *fractal, const char *fileName, FILE *file, const char *format) * \brief Create fractal from fractal file body. * * The body of a fractal file is everything that comes after * the format version.\n * fileName is used only for error messages.\n * This function should only be used internally by the library. * * \param fractal Pointer to the fractal structure to create. * \param fileName Fractal file name. * \param file Pointer to opened file, positioned at the beginning of the body. * \param format Fractal file format. * \return 0 in case of success, 1 in case of failure. */ int ReadFractalFileBody(Fractal *fractal, const char *fileName, FILE *file, const char *format); /** * \fn int ReadFractalFile(Fractal *fractal, const char *fileName) * \brief Read and parse a fractal file, and create the according fractal. * * \param fractal Pointer to the fractal structure to create. * \param fileName Fractal file name. * \return 0 in case of success, 1 in case of failure. */ int ReadFractalFile(Fractal *fractal, const char *fileName); /** * \fn int WriteFractalFileBody(const Fractal *fractal, const char *fileName, FILE *file, const char *format) * \brief Write fractal file body. * * The body of a fractal file is everything that comes after * the format version.\n * fileName is used only for error messages.\n * This function should only be used internally by the library. * * \param fractal Fractal to write into file. * \param fileName Fractal file name. * \param file Pointer to opened file, positioned at the beginning of the body. * \param format Fractal file format. * \return 0 in case of success, 1 in case of failure. */ int WriteFractalFileBody(const Fractal *fractal, const char *fileName, FILE *file, const char *format); /** * \fn int WriteFractalFile(const Fractal *fractal, const char *fileName) * \brief Read and parse a fractal file, and create the according fractal. * * \param fractal Fractal to write into file. * \param fileName Fractal file name. * \return 0 in case of success, 1 in case of failure. */ int WriteFractalFile(const Fractal *fractal, const char *fileName); /** * \fn void DrawFractal(Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t quadInterpolationSize, double interpolationThreshold, FloatPrecision floatPrecision, FractalCache *cache, Threads* threads) * \brief Draw fractal in a fast, approximate way. * * Image width and height must be >= 2 (does nothing otherwise).\n * Details on the algorithm : * The image is cut in quads (rectangles, actually) of size * quadInterpolationSize (meaning width AND height <= size).\n * Then for each quad, its corner colors are computed, and depending * on its dissimilarity (average difference of the corner colors to the * average color of the corners), the quad is either computed or linearly * interpolated.\n * Default values of quadInterpolationSize and interpolationThreshold * are good for no visible loss of quality.\n * Pointer to cache structure can be NULL if no cache is to be used.\n * If cache is not NULL, it must point to a created cache structure, * and it is used to generate a preview of the image, and speed-up * the task by using values computed by a previous fractal drawing * or anti-aliasing. * * \param image Image in which to draw fractal subset. * \param fractal Fractal subset to compute. * \param render Rendering parameters. * \param quadInterpolationSize Maximum quad size for interpolation. * \param interpolationThreshold Dissimilarity threshold for interpolation. * \param floatPrecision Float precision. * \param cache Cache structure to put computed values in. * \param threads Threads to be used for task. */ void DrawFractal(Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t quadInterpolationSize, double interpolationThreshold, FloatPrecision floatPrecision, FractalCache *cache, Threads* threads); /** * \fn Task *CreateDrawFractalTask(Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t quadInterpolationSize, double interpolationThreshold, FloatPrecision floatPrecision, FractalCache *cache, uint_fast32_t nbThreads) * \brief Create fractal drawing task. * * Create task and return immediately.\n * Task structure can be used to query progress, send * cancellation request, etc.\n * Image width and height must be >= 2 (does nothing otherwise).\n * When launching task, Threads structure should provide * enough threads (at least number specified here). * Pointer to cache structure can be NULL if no cache is to be used. * * \param image Image in which to draw fractal subset. * \param fractal Fractal subset to compute. * \param render Rendering parameters. * \param quadInterpolationSize Maximum quad size for interpolation. * \param interpolationThreshold Dissimilarity threshold for interpolation. * \param floatPrecision Float precision. * \param cache Cache structure to put computed values in. * \param nbThreads Number of threads that action will need to be launched. * \return Corresponding newly-allocated task. */ Task *CreateDrawFractalTask(Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t quadInterpolationSize, double interpolationThreshold, FloatPrecision floatPrecision, FractalCache *cache, uint_fast32_t nbThreads); /** * \fn void AntiAliaseFractal(Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t antiAliasingSize, double threshold, FloatPrecision floatPrecision, FractalCache *cache, Threads *threads) * \brief AntiAliase fractal image. * * Image width and height must be >= 2 (does nothing otherwise).\n * Anti-aliasing size must be >= 2 to have an effect (does nothing otherwise). * * Details on the algorithm : * Pixels that differ too much from neighbour pixels * (difference greater than threshold) are recomputed.\n * Several pixels (antiAliasingSize^2 to be precise) are computed * for each of these preselected pixels, and averaged (with gaussian * filter) to produce the new pixel value.\n * Default threshold value is good to obtain a result similar to * oversampling (computing a bigger image and downscaling it) with * the same size factor.\n * Pointer to cache structure can be NULL if no cache is to be used.\n * Note that for anti-aliasing, cache is not used to generate of preview * of the image and speed-up task: it is only filled with the values * computed when anti-aliasing. * * \param image Fractal image (already drawn) to anti-aliase. * \param fractal Fractal subset to compute. * \param render Rendering parameters. * \param antiAliasingSize Anti-aliasing size. * \param threshold Dissimilarity threshold to determine pixels to recompute. * \param floatPrecision Float precision. * \param cache Cache structure to put computed values in. * \param threads Threads to be used for task. */ void AntiAliaseFractal(Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t antiAliasingSize, double threshold, FloatPrecision floatPrecision, FractalCache *cache, Threads *threads); /** * \fn Task *CreateAntiAliaseFractalTask(Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t antiAliasingSize, double threshold, FloatPrecision floatPrecision, FractalCache *cache, uint_fast32_t nbThreads) * \brief Create task anti-aliasing fractal image * * Create task and return immediately.\n * Image width and height must be >= 2 (does nothing otherwise).\n * Anti-aliasing size must be >= 2 to have an effect (does nothing otherwise).\n * When launching task, Threads structure should provide * enough threads (at least number specified here). * * \param image Fractal image (already drawn) to anti-aliase. * \param fractal Fractal subset to compute. * \param render Rendering parameters. * \param antiAliasingSize Anti-aliasing size. * \param threshold Dissimilarity threshold to determine pixels to recompute. * \param floatPrecision Float precision. * \param cache Cache structure to put computed values in. * \param nbThreads Number of threads that action will need to be launched. * \return Corresponding newly-allocated task. */ Task *CreateAntiAliaseFractalTask(Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t antiAliasingSize, double threshold, FloatPrecision floatPrecision, FractalCache *cache, uint_fast32_t nbThreads); /** * \fn void FreeFractal(Fractal fractal) * \brief Free a fractal structure. * * \param fractal Fractal structure to be freed. */ void FreeFractal(Fractal fractal); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/config_files/config12.config000664 001750 001750 00000000236 13175112471 022654 0ustar00mpegmpeg000000 000000 c075 julia 0.5 0.25 0 0 2.57775119617225 2.57775119617225 10000000 100 1 0x0 averagecoloring triangleinequality linear cube 1 0 0 0xffffff 0.5 0x0 1 0xffffff fractalnow-0.8.2/lib/src/ppm.c000664 001750 001750 00000004754 13175112471 016116 0ustar00mpegmpeg000000 000000 /* * ppm.c -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "ppm.h" #include "error.h" #include int aux_ExportPPM8(const char *fileName, const Image *image) { FILE *file; int res = 0; file = fopen(fileName,"wb"); if (!file) { FractalNow_open_werror(fileName); } fprintf(file,"P6\n%"PRIuFAST32" %"PRIuFAST32"\n%"PRIu8"\n", image->width, image->height, (uint8_t)UINT8_MAX); if (image->width != 0 && image->height != 0) { uint8_t *bytes = ImageToBytesArray(image); fwrite(bytes, 3, image->width*image->height, file); free(bytes); } end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } return res; } int aux_ExportPPM16(const char *fileName, const Image *image) { FILE *file; int res = 0; file = fopen(fileName,"wb"); if (!file) { FractalNow_open_werror(fileName); } fprintf(file,"P6\n%"PRIuFAST32" %"PRIuFAST32"\n%"PRIu16"\n", image->width, image->height, (uint16_t)UINT16_MAX); if (image->width != 0 && image->height != 0) { uint8_t *bytes = ImageToBytesArray(image); fwrite(bytes, 6, image->width*image->height, file); free(bytes); } end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } return res; } int ExportPPM(const char *fileName, const Image *image) { int res = 0; FractalNow_message(stdout, T_NORMAL, "Exporting PPM \'%s\'...\n", fileName); switch (image->bytesPerComponent) { case 1: res = aux_ExportPPM8(fileName, image); break; case 2: res = aux_ExportPPM16(fileName, image); break; default: FractalNow_error("Invalid image bytes per component.\n"); break; } FractalNow_message(stdout, T_NORMAL, "Exporting PPM \'%s\' : %s.\n", fileName, (res == 0) ? "DONE" : "FAILED"); return res; } fractalnow-0.8.2/lib/src/error.c000664 001750 001750 00000001640 13175112471 016442 0ustar00mpegmpeg000000 000000 /* * error.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "error.h" int FractalNow_debug = 0; TraceLevel FractalNow_traceLevel = T_NORMAL; fractalnow-0.8.2/examples/rendering_files/render02b.render000664 001750 001750 00000000132 13175112471 023544 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING TRIANGLEINEQUALITY NONE CUBE 1 0 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/command-line/include/000775 001750 001750 00000000000 13175112471 017575 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/examples/rendering_files/render01a.render000664 001750 001750 00000000115 13175112471 023543 0ustar00mpegmpeg000000 000000 R075 1 0x0 ITERATIONCOUNT SMOOTH LOG 3.25E-1 0 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/lib/src/task.c000664 001750 001750 00000035260 13175112471 016260 0ustar00mpegmpeg000000 000000 /* * task.c -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "task.h" #include "error.h" #include "misc.h" #include #define ARG_SIZE (size_t)(sizeof(ThreadArgHeader *)+sizeof(void *)) static inline int ReadIntVarSafe(int *variable, pthread_spinlock_t *mutex) { int res; safePThreadSpinLock(mutex); res = *variable; safePThreadSpinUnlock(mutex); return res; } static inline void WriteIntVarSafe(int *variable, int value, pthread_spinlock_t *mutex) { safePThreadSpinLock(mutex); *variable = value; safePThreadSpinUnlock(mutex); } void *DoNothingThreadRoutine(void *arg) { ThreadArgHeader *c_arg = GetThreadArgHeader(arg); HandlePauseRequest(c_arg); return (CancelTaskRequested(c_arg) ? PTHREAD_CANCELED : NULL); } void FreeArgDoNothing(void *arg) { UNUSED(arg); } #ifdef DEBUG char DoNothingMessage[] = "Doing nothing"; #else char *DoNothingMessage = NULL; #endif Task *DoNothingTask() { return CreateTask(DoNothingMessage, 0, NULL, 0, DoNothingThreadRoutine, FreeArgDoNothing); } static inline Task *aux_CreateTask(const char message[], uint_fast32_t nbThreadsNeeded, size_t s_elem, void *(*routine)(void *), void (*freeArg)(void *)) { Task *res = (Task *)safeMalloc("task", sizeof(Task)); res->launchPrepared = 0; res->hasBeenLaunched = 0; res->done = 0; res->returnValue = -1; res->nbThreadsNeeded = nbThreadsNeeded; res->initialArgs = NULL; safePThreadSpinInit(&res->cancelMutex, SPIN_INIT_ATTR); WriteIntVarSafe(&res->cancel, 0, &res->cancelMutex); safePThreadSpinInit(&res->pauseMutex, SPIN_INIT_ATTR); WriteIntVarSafe(&res->pause, 0, &res->pauseMutex); res->isComposite = 0; res->compositeTaskArguments.thisTask = NULL; res->nbSubTasks = 0; res->subTasks = NULL; res->compositeTaskNbReady = 0; res->stopLaunchingSubTasks = 0; safePThreadCondInit(&res->compositeTaskAllThreadsReadyCond, NULL); res->s_elem = s_elem; if (freeArg == NULL) { res->freeArg = FreeArgDoNothing; } else { res->freeArg = freeArg; } if (message == NULL) { res->message = NULL; } else { res->message = (char *)safeMalloc("message", (strlen(message)+1)*sizeof(char)); strcpy(res->message, message); } res->threadsRoutine = routine; return res; } inline Task *CreateTask(const char message[], uint_fast32_t nbThreadsNeeded, const void *args, size_t s_elem, void *(*routine)(void *), void (*freeArg)(void *)) { Task *res = aux_CreateTask(message, nbThreadsNeeded, s_elem, routine, freeArg); if (res->s_elem > 0) { res->initialArgs = safeMalloc("thread args", nbThreadsNeeded * s_elem); memcpy(res->initialArgs, args, nbThreadsNeeded * s_elem); } return res; } void *CompositeTaskRoutine(void *arg); Task *CreateCompositeTask(const char message[], uint_fast32_t nbSubTasks, Task *subTasks[]) { if (nbSubTasks == 0) { FractalNow_error("Number of subtasks must be > 0 when creating composite task.\n"); } uint_fast32_t nbThreadsNeeded = subTasks[0]->nbThreadsNeeded; for (uint_fast32_t i = 1; i < nbSubTasks; ++i) { if (subTasks[i]->nbThreadsNeeded > nbThreadsNeeded) { nbThreadsNeeded = subTasks[i]->nbThreadsNeeded; } } Task *res = aux_CreateTask(message, nbThreadsNeeded, sizeof(CompositeTaskArguments), CompositeTaskRoutine, NULL); res->isComposite = 1; res->compositeTaskArguments.thisTask = res; res->nbSubTasks = nbSubTasks; res->subTasks = (Task **)safeMalloc("copy subtasks", nbSubTasks*sizeof(Task *)); memcpy(res->subTasks, subTasks, nbSubTasks*sizeof(Task *)); return res; } /* nbReady override for tasks that are subtasks. */ static void PrepareLaunchTask(Task *task, Threads *threads, uint_fast32_t *nbReadyOverride) { task->threads = threads; task->threadArgsHeaders = (ThreadArgHeader *)safeMalloc("thread arg headers", threads->N * sizeof(ThreadArgHeader)); task->args = (void *)safeMalloc("thread args", threads->N * ARG_SIZE); uint8_t *task_args = (uint8_t *)task->args; uint8_t *c_args = (uint8_t *)task->initialArgs; ThreadArgHeader *threadArgHeader = task->threadArgsHeaders; for (uint_fast32_t i = 0; i < threads->N; ++i) { threadArgHeader->threadId = i; threadArgHeader->threads = threads; if (nbReadyOverride != NULL) { threadArgHeader->nbReady = nbReadyOverride; } else { threadArgHeader->nbReady = &threads->nbReady; } threadArgHeader->cancel = &task->cancel; threadArgHeader->cancelMutex = &task->cancelMutex; threadArgHeader->pause = &task->pause; threadArgHeader->pauseMutex = &task->pauseMutex; threadArgHeader->progress = 0; safePThreadSpinInit(&threadArgHeader->progressMutex, SPIN_INIT_ATTR); *((ThreadArgHeader **)task_args) = threadArgHeader; if (task->isComposite) { *((void **)(task_args + sizeof(ThreadArgHeader *))) = &task->compositeTaskArguments; } else { if (i < task->nbThreadsNeeded) { *((void **)(task_args + sizeof(ThreadArgHeader *))) = c_args; c_args += task->s_elem; } else { *((void **)(task_args + sizeof(ThreadArgHeader *))) = NULL; } } task_args += ARG_SIZE; ++threadArgHeader; } if (task->isComposite) { for (uint_fast32_t i = 0; i < task->nbSubTasks; ++i) { PrepareLaunchTask(task->subTasks[i], threads, &task->compositeTaskNbReady); } } task->launchPrepared = 1; } void LaunchTask(Task *task, Threads *threads) { if (task->hasBeenLaunched) { FractalNow_error("Trying to launch task that has already been launched.\n"); } safePThreadMutexLock(&threads->threadsMutex); if (threads->nbReady < threads->N) { FractalNow_error("Trying to launch task while threads are still busy.\n"); } safePThreadMutexUnlock(&threads->threadsMutex); PrepareLaunchTask(task, threads, NULL); uint8_t *task_args = (uint8_t *)task->args; safePThreadMutexLock(&threads->startThreadCondMutex); for (uint_fast32_t i = 0; i < threads->N; ++i) { threads->startThreadArg[i].message = task->message; if (task->isComposite || i < task->nbThreadsNeeded) { threads->startThreadArg[i].startRoutine = task->threadsRoutine; } else { threads->startThreadArg[i].startRoutine = DoNothingThreadRoutine; } threads->startThreadArg[i].arg = task_args; task_args += ARG_SIZE; } /* Reinit nbReady counter. */ threads->nbReady = 0; threads->nbPaused = 0; task->hasBeenLaunched = 1; if (task->message != NULL) { FractalNow_message(stdout, T_NORMAL, "%s...\n", task->message); } safePThreadCondBroadcast(&threads->startThreadCond); safePThreadMutexUnlock(&threads->startThreadCondMutex); } void CancelTask(Task *task) { if (task->isComposite) { for (uint_fast32_t i = 0; i < task->nbSubTasks; ++i) { CancelTask(task->subTasks[i]); } } WriteIntVarSafe(&task->cancel, 1, &task->cancelMutex); } static inline void aux_PauseTask(Task *task) { if (task->isComposite) { WriteIntVarSafe(&task->pause, 1, &task->pauseMutex); for (uint_fast32_t i = 0; i < task->nbSubTasks; ++i) { aux_PauseTask(task->subTasks[i]); } } else { WriteIntVarSafe(&task->pause, 1, &task->pauseMutex); } } void PauseTask(Task *task) { if (!task->hasBeenLaunched || task->done) { return; } int pause = ReadIntVarSafe(&task->pause, &task->pauseMutex); if (pause) { return; } Threads *threads = task->threads; safePThreadMutexLock(&threads->threadsMutex); if (threads->nbReady < threads->N) { threads->nbPaused = 0; aux_PauseTask(task); safePThreadCondWait(&threads->allPausedCond, &threads->threadsMutex); } safePThreadMutexUnlock(&threads->threadsMutex); } static inline void aux_ResumeTask(Task *task) { if (task->isComposite) { for (uint_fast32_t i = 0; i < task->nbSubTasks; ++i) { aux_ResumeTask(task->subTasks[i]); } WriteIntVarSafe(&task->pause, 0, &task->pauseMutex); } else { WriteIntVarSafe(&task->pause, 0, &task->pauseMutex); } } void ResumeTask(Task *task) { if (!task->hasBeenLaunched || task->done) { return; } Threads *threads = task->threads; safePThreadMutexLock(&task->threads->threadsMutex); aux_ResumeTask(task); if (threads->nbPaused > 0) { safePThreadCondBroadcast(&threads->resumeTaskCond); safePThreadCondWait(&threads->allResumedCond, &threads->threadsMutex); } safePThreadMutexUnlock(&threads->threadsMutex); } void onTaskFinished(Task *task) { void *status; for (uint_fast32_t i = 0; i < task->threads->N; ++i) { status = task->threads->lastResult[i]; if (status != NULL && status != PTHREAD_CANCELED) { FractalNow_message(stderr, T_QUIET, "Thread ended because of an error.\n"); } } task->done = 1; task->returnValue = ReadIntVarSafe(&task->cancel, &task->cancelMutex); if (task->message != NULL) { FractalNow_message(stdout, T_NORMAL, "%s : %s.\n", task->message, (task->returnValue == 0) ? "DONE" : "CANCELED"); } } int TaskIsFinished(Task *task) { if (task->done) { return 1; } if (!task->hasBeenLaunched) { return 0; } uint_fast32_t nbReady = 0; safePThreadMutexLock(&task->threads->threadsMutex); nbReady = task->threads->nbReady; safePThreadMutexUnlock(&task->threads->threadsMutex); int res = 0; if (nbReady == task->threads->N) { onTaskFinished(task); res = 1; } return res; } inline int GetTaskResult(Task *task) { if (task->done) { return task->returnValue; } if (!task->hasBeenLaunched) { FractalNow_error("Cannot get result of not-yet-launched task.\n"); } uint_fast32_t nbReady = 0; safePThreadMutexLock(&task->threads->threadsMutex); nbReady = task->threads->nbReady; if (nbReady < task->threads->N) { safePThreadCondWait(&task->threads->allThreadsReadyCond, &task->threads->threadsMutex); nbReady = task->threads->nbReady; } safePThreadMutexUnlock(&task->threads->threadsMutex); onTaskFinished(task); return task->returnValue; } int ExecuteTaskBlocking(Task *task, Threads *threads) { LaunchTask(task, threads); int res = GetTaskResult(task); FreeTask(task); return res; } double GetTaskProgress(const Task *task) { double res; if (!task->hasBeenLaunched) { res = 0; } else if (task->done) { res = 1; } else if (!task->isComposite) { res = 0; for (uint_fast32_t i = 0; i < task->nbThreadsNeeded; ++i) { res += ReadIntVarSafe(&task->threadArgsHeaders[i].progress, &task->threadArgsHeaders[i].progressMutex); } res /= 100 * task->nbThreadsNeeded; } else { res = 0; for (uint_fast32_t i = 0; i < task->nbSubTasks; ++i) { res += GetTaskProgress(task->subTasks[i]); } res /= task->nbSubTasks; } return res; } inline void FreeTask(Task *task) { if (task->hasBeenLaunched && !task->done) { FractalNow_error("Trying to free non-finished task.\n"); } uint8_t *c_arg = (uint8_t *)task->initialArgs; for (uint_fast32_t i = 0; i < task->nbThreadsNeeded; ++i) { task->freeArg(c_arg); c_arg += task->s_elem; } if (task->initialArgs != NULL) { free(task->initialArgs); } if (task->launchPrepared) { Threads *threads = task->threads; for (uint_fast32_t i = 0; i < threads->N; ++i) { safePThreadSpinDestroy(&task->threadArgsHeaders[i].progressMutex); } free(task->threadArgsHeaders); free(task->args); } if (task->message != NULL) { free(task->message); } if (task->isComposite) { for (uint_fast32_t i = 0; i < task->nbSubTasks; ++i) { FreeTask(task->subTasks[i]); } free(task->subTasks); } safePThreadSpinDestroy(&task->cancelMutex); safePThreadSpinDestroy(&task->pauseMutex); safePThreadCondDestroy(&task->compositeTaskAllThreadsReadyCond); free(task); } static inline void CompositeTaskRendezVous(ThreadArgHeader *threadArgHeader, Task *thisTask, Task *finishedTask, Task *newTask, uint_fast32_t i) { Threads *threads = threadArgHeader->threads; safePThreadMutexLock(&threads->threadsMutex); ++thisTask->compositeTaskNbReady; if (threads->nbPaused > 0 && thisTask->compositeTaskNbReady+threads->nbPaused == threads->N) { safePThreadCondSignal(&threads->allPausedCond); } if (finishedTask != NULL && finishedTask->message != NULL) { FractalNow_message(stdout, T_VERBOSE, "%s [%"PRIuFAST32"] : %s.\n", finishedTask->message, threadArgHeader->threadId, threads->lastResult[threadArgHeader->threadId] == NULL ? "DONE" : "CANCELED"); } if (thisTask->compositeTaskNbReady == threads->N) { if (finishedTask != NULL) { onTaskFinished(finishedTask); } if (newTask != NULL) { if (CancelTaskRequested(threadArgHeader)) { thisTask->stopLaunchingSubTasks = 1; } else { threadArgHeader->progress = 100 * i / thisTask->nbSubTasks; thisTask->compositeTaskNbReady = 0; newTask->hasBeenLaunched = 1; if (newTask->message != NULL) { FractalNow_message(stdout, T_NORMAL, "%s...\n", newTask->message); } } } else { threadArgHeader->progress = 100; } safePThreadCondBroadcast(&thisTask->compositeTaskAllThreadsReadyCond); } else { safePThreadCondWait(&thisTask->compositeTaskAllThreadsReadyCond, &threads->threadsMutex); } safePThreadMutexUnlock(&threads->threadsMutex); } void *CompositeTaskRoutine(void *arg) { ThreadArgHeader *threadArgHeader = GetThreadArgHeader(arg); CompositeTaskArguments *c_arg = (CompositeTaskArguments *)GetThreadArgBody(arg); Task *thisTask = c_arg->thisTask; Task *currentTask = NULL; Task *previousTask = NULL; void *result; int canceled = 0; uint_fast32_t i; for (i = 0; i < thisTask->nbSubTasks; ++i) { previousTask = currentTask; currentTask = thisTask->subTasks[i]; CompositeTaskRendezVous(threadArgHeader, thisTask, previousTask, currentTask, i); if (thisTask->stopLaunchingSubTasks) { canceled = 1; break; } else { if (currentTask->message != NULL) { FractalNow_message(stdout, T_VERBOSE, "%s [%"PRIuFAST32"]...\n", currentTask->message, threadArgHeader->threadId); } if (currentTask->isComposite || threadArgHeader->threadId < currentTask->nbThreadsNeeded) { result = currentTask->threadsRoutine(((uint8_t *)currentTask->args)+ threadArgHeader->threadId*ARG_SIZE); } else { result = DoNothingThreadRoutine(((uint8_t *)currentTask->args)+ threadArgHeader->threadId*ARG_SIZE); } currentTask->threads->lastResult[threadArgHeader->threadId] = result; } } if (!canceled) { CompositeTaskRendezVous(threadArgHeader, thisTask, currentTask, NULL, i); } return (CancelTaskRequested(threadArgHeader) ? PTHREAD_CANCELED : NULL); } fractalnow-0.8.2/lib/src/fractal_rendering_parameters.c000664 001750 001750 00000027774 13175115345 023230 0ustar00mpegmpeg000000 000000 /* * fractal_rendering_parameters.c -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "fractal_rendering_parameters.h" #include "error.h" #include "file_io.h" #include "misc.h" #include #include #include const char *renderingFileFormatStr[] = { (const char *)"r075" }; const uint_fast32_t nbRenderingFileFormats = sizeof(renderingFileFormatStr) / sizeof(const char *); int ReadRenderingFileV075(RenderingParameters *param, const char *fileName, FILE *file); typedef int (*ReadRenderingFileFunction)(RenderingParameters *param, const char *fileName, FILE *file); const ReadRenderingFileFunction readRenderingFileFunction[] = { ReadRenderingFileV075 }; int WriteRenderingFileV075(const RenderingParameters *param, const char *fileName, FILE *file); typedef int (*WriteRenderingFileFunction)(const RenderingParameters *param, const char *fileName, FILE *file); const WriteRenderingFileFunction writeRenderingFileFunction[] = { WriteRenderingFileV075 }; inline void InitRenderingParameters(RenderingParameters *param, uint_fast8_t bytesPerComponent, Color spaceColor, IterationCount iterationCount, ColoringMethod coloringMethod, AddendFunction addendFunction, uint_fast32_t stripeDensity, InterpolationMethod interpolationMethod, TransferFunction transferFunction, double multiplier, double offset, Gradient gradient) { param->bytesPerComponent = bytesPerComponent; param->spaceColor = spaceColor; param->iterationCount = iterationCount; param->coloringMethod = coloringMethod; param->addendFunction = addendFunction; param->stripeDensity = stripeDensity; param->interpolationMethod = interpolationMethod; param->transferFunction = transferFunction; param->transferFunctionPtr = GetTransferFunctionPtr(transferFunction); param->multiplier = multiplier; param->realMultiplier = multiplier*gradient.size; param->offset = offset; param->realOffset = offset*gradient.size; param->gradient = gradient; } RenderingParameters CopyRenderingParameters(const RenderingParameters *param) { Gradient copyGradient = CopyGradient(¶m->gradient); RenderingParameters res; InitRenderingParameters(&res, param->bytesPerComponent, param->spaceColor, param->iterationCount, param->coloringMethod, param->addendFunction, param->stripeDensity, param->interpolationMethod, param->transferFunction, param->multiplier, param->offset, copyGradient); return res; } void ResetGradient(RenderingParameters *param, Gradient gradient) { FreeGradient(param->gradient); param->gradient = CopyGradient(&gradient); param->bytesPerComponent = gradient.bytesPerComponent; param->realMultiplier = param->multiplier*gradient.size; param->realOffset = param->offset*gradient.size; } int ReadRenderingFileV075(RenderingParameters *param, const char *fileName, FILE *file) { int res = 0; uint_fast8_t bytesPerComponent; Color spaceColor; IterationCount iterationCount; ColoringMethod coloringMethod; AddendFunction addendFunction; uint32_t stripeDensity; InterpolationMethod interpolationMethod; TransferFunction transferFunction; double multiplier; double offset; Gradient gradient; char str[256]; uint32_t bytesPerComponent32; if (readUint32(file, &bytesPerComponent32) < 1) { FractalNow_read_werror(fileName); } if (bytesPerComponent32 == 1 || bytesPerComponent32 == 2) { bytesPerComponent = (uint_fast8_t)bytesPerComponent32; } else { FractalNow_werror("Invalid rendering file : bytes per components must be 1 or 2.\n"); } if (readColor(file, bytesPerComponent, &spaceColor) < 1) { FractalNow_read_werror(fileName); } if (readString(file, str) < 1) { FractalNow_read_werror(fileName); } if (GetColoringMethod(&coloringMethod, str)) { FractalNow_werror("Invalid rendering file : could not get coloring method.\n"); } /* Just to be sure these are initialized, because they are always needed (and thus read). */ iterationCount = IC_SMOOTH; interpolationMethod = IM_NONE; addendFunction = AF_TRIANGLEINEQUALITY; stripeDensity = 1; switch (coloringMethod) { case CM_ITERATIONCOUNT: if (readString(file, str) < 1) { FractalNow_read_werror(fileName); } if (GetIterationCount(&iterationCount, str)) { FractalNow_werror("Invalid rendering file : could not get counting function.\n"); } break; case CM_AVERAGECOLORING: if (readString(file, str) < 1) { FractalNow_read_werror(fileName); } if (GetAddendFunction(&addendFunction, str)) { FractalNow_werror("Invalid rendering file : could not get addend function.\n"); } if (addendFunction == AF_STRIPE) { if (readUint32(file, &stripeDensity) < 1) { FractalNow_read_werror(fileName); } } if (readString(file, str) < 1) { FractalNow_read_werror(fileName); } if (GetInterpolationMethod(&interpolationMethod, str)) { FractalNow_werror("Invalid rendering file : could not get interpolation method.\n"); } break; default: FractalNow_werror("Unknown coloring method.\n"); break; } if (readString(file, str) < 1) { FractalNow_read_werror(fileName); } if (GetTransferFunction(&transferFunction, str)) { FractalNow_werror("Invalid rendering file : could not get transfer function.\n"); } if (readDouble(file, &multiplier) < 1) { FractalNow_read_werror(fileName); } if (readDouble(file, &offset) < 1) { FractalNow_read_werror(fileName); } if (ReadGradientFileBody(&gradient, bytesPerComponent, fileName, file, "g073")) { FractalNow_werror("Invalid rendering file : failed to read gradient.\n"); } InitRenderingParameters(param, bytesPerComponent, spaceColor, iterationCount, coloringMethod, addendFunction, stripeDensity, interpolationMethod, transferFunction, multiplier, offset, gradient); end: return res; } ReadRenderingFileFunction GetReadRenderingFileFunction(const char *format) { if (strlen(format) != 4) { return NULL; } ReadRenderingFileFunction readRenderingFile = NULL; char formatStr[5]; strcpy(formatStr, format); toLowerCase(formatStr); uint_fast32_t i; for (i = 0; i < nbRenderingFileFormats; ++i) { if (strcmp(formatStr, renderingFileFormatStr[i]) == 0) { readRenderingFile = readRenderingFileFunction[i]; break; } } return readRenderingFile; } int isSupportedRenderingFile(const char *fileName) { int res = 0; FILE *file; file=fopen(fileName,"r"); if (!file) { FractalNow_open_werror(fileName); } char formatStr[256]; if (readString(file, formatStr) < 1) { res = 1; } else { ReadRenderingFileFunction readRenderingFileFunction; readRenderingFileFunction = GetReadRenderingFileFunction(formatStr); res = (readRenderingFileFunction == NULL); } end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } return !res; } int ReadRenderingFileBody(RenderingParameters *param, const char *fileName, FILE *file, const char *format) { FractalNow_message(stdout, T_VERBOSE, "Reading rendering file body...\n"); int res = 0; ReadRenderingFileFunction readRenderingFile; readRenderingFile = GetReadRenderingFileFunction(format); if (readRenderingFile == NULL) { FractalNow_werror("Unsupported rendering file format '%s'.\n", format); } res |= readRenderingFile(param, fileName, file); end: FractalNow_message(stdout, T_VERBOSE, "Reading rendering file body : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } int ReadRenderingFile(RenderingParameters *param, const char *fileName) { FractalNow_message(stdout, T_NORMAL, "Reading rendering file...\n"); int res = 0; FILE *file; file=fopen(fileName,"r"); if (!file) { FractalNow_open_werror(fileName); } char formatStr[256]; if (readString(file, formatStr) < 1) { FractalNow_read_werror(fileName); } res = ReadRenderingFileBody(param, fileName, file, formatStr); end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } FractalNow_message(stdout, T_NORMAL, "Reading rendering file : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } int WriteRenderingFileV075(const RenderingParameters *param, const char *fileName, FILE *file) { int res = 0; if (writeUint32(file, param->bytesPerComponent, "\n") < 0) { FractalNow_write_werror(fileName); } if (writeColor(file, param->spaceColor, "\n") < 0) { FractalNow_write_werror(fileName); } if (writeString(file, coloringMethodStr[(int)param->coloringMethod], "\n") < 0) { FractalNow_write_werror(fileName); } switch (param->coloringMethod) { case CM_ITERATIONCOUNT: if (writeString(file, iterationCountStr[(int)param->iterationCount], "\n") < 0) { FractalNow_write_werror(fileName); } break; case CM_AVERAGECOLORING: if (writeString(file, addendFunctionStr[(int)param->addendFunction], " ") < 0) { FractalNow_write_werror(fileName); } if (param->addendFunction == AF_STRIPE) { if (writeUint32(file, param->stripeDensity, " ") < 0) { FractalNow_write_werror(fileName); } } if (writeString(file, interpolationMethodStr[(int)param->interpolationMethod], "\n") < 0) { FractalNow_write_werror(fileName); } break; default: FractalNow_werror("Unknown coloring method.\n"); break; } if (writeString(file, transferFunctionStr[(int)param->transferFunction], "\n") < 0) { FractalNow_write_werror(fileName); } if (writeDouble(file, param->multiplier, " ") < 0) { FractalNow_write_werror(fileName); } if (writeDouble(file, param->offset, "\n") < 0) { FractalNow_write_werror(fileName); } if (WriteGradientFileBody(¶m->gradient, fileName, file, "g073")) { FractalNow_werror("Failed to write gradient.\n"); } end: return res; } WriteRenderingFileFunction GetWriteRenderingFileFunction(const char *format) { if (strlen(format) != 4) { return NULL; } WriteRenderingFileFunction writeRenderingFile = NULL; char formatStr[5]; strcpy(formatStr, format); toLowerCase(formatStr); uint_fast32_t i; for (i = 0; i < nbRenderingFileFormats; ++i) { if (strcmp(formatStr, renderingFileFormatStr[i]) == 0) { writeRenderingFile = writeRenderingFileFunction[i]; break; } } return writeRenderingFile; } int WriteRenderingFileBody(const RenderingParameters *param, const char *fileName, FILE *file, const char *format) { FractalNow_message(stdout, T_VERBOSE, "Writing rendering file body...\n"); int res = 0; WriteRenderingFileFunction writeRenderingFile; writeRenderingFile = GetWriteRenderingFileFunction(format); if (writeRenderingFile == NULL) { FractalNow_werror("Unsupported rendering file format '%s'.\n", format); } res |= writeRenderingFile(param, fileName, file); end: FractalNow_message(stdout, T_VERBOSE, "Writing rendering file body : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } int WriteRenderingFile(const RenderingParameters *param, const char *fileName) { FractalNow_message(stdout, T_NORMAL, "Writing rendering file...\n"); int res = 0; FILE *file; file=fopen(fileName,"w"); if (!file) { FractalNow_open_werror(fileName); } const char *format = renderingFileFormatStr[nbRenderingFileFormats-1]; if (writeString(file, format, "\n") < 0) { FractalNow_write_werror(fileName); } res = WriteRenderingFileBody(param, fileName, file, format); end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } FractalNow_message(stdout, T_NORMAL, "Writing rendering file : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } void FreeRenderingParameters(RenderingParameters param) { FreeGradient(param.gradient); } fractalnow-0.8.2/lib/src/fractal_addend_function.c000664 001750 001750 00000003471 13175115345 022140 0ustar00mpegmpeg000000 000000 /* * fractal_addend_function.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "fractal.h" #include "fractal_addend_function.h" #include "misc.h" #include const char *addendFunctionStr[] = { (const char *)"triangleinequality", (const char *)"curvature", (const char *)"stripe" }; const char *addendFunctionDescStr[] = { (const char *)"Triangle inequality", (const char *)"Curvature", (const char *)"Stripe" }; const uint_fast32_t nbAddendFunctions = sizeof(addendFunctionStr) / sizeof(const char *); int GetAddendFunction(AddendFunction *addendFunction, const char *str) { int res = 0; int len = strlen(str); if (len > 255) { FractalNow_werror("Unknown addend function \'%s\'.\n", str); } char AFStr[256]; strcpy(AFStr, str); toLowerCase(AFStr); uint_fast32_t i; for (i = 0; i < nbAddendFunctions; ++i) { if (strcmp(AFStr, addendFunctionStr[i]) == 0) { *addendFunction = (AddendFunction)i; break; } } if (i == nbAddendFunctions) { FractalNow_werror("Unknown addend function \'%s\'.\n", str); } end: return res; } fractalnow-0.8.2/lib/src/misc.c000664 001750 001750 00000003760 13175115345 016254 0ustar00mpegmpeg000000 000000 /* * misc.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "misc.h" #include "error.h" #include #ifdef _ENABLE_MP_FLOATS #include #include #include #endif void toLowerCase(char *str) { for (; *str != '\0'; ++str) { *str = tolower(*str); } } void *safeMalloc(const char *name, uint_least64_t size) { if (size > SIZE_MAX) { FractalNow_alloc_error(name); } void *res = malloc((size_t)size); if (size > 0 && res == NULL) { FractalNow_alloc_error(name); } return res; } void *safeRealloc(const char *name, void *ptr, uint_least64_t size) { if (size > SIZE_MAX) { FractalNow_alloc_error(name); } void *res = realloc(ptr, (size_t)size); if (size > 0 && res == NULL) { FractalNow_alloc_error(name); } return res; } void *safeCalloc(const char *name, uint_least64_t nmemb, uint_least64_t size) { if (nmemb > SIZE_MAX || size > SIZE_MAX) { FractalNow_alloc_error(name); } void *res = calloc((size_t)nmemb, (size_t)size); if (size > 0 && res == NULL) { FractalNow_alloc_error(name); } return res; } #ifdef _ENABLE_MP_FLOATS int mpcIsInteger(const mpc_t x) { if (mpfr_cmp_ui(mpc_imagref(x), 0) != 0) { return 0; } else { return mpfr_integer_p(mpc_realref(x)); } } #endif fractalnow-0.8.2/lib/include/fractal_rendering_parameters.h000664 001750 001750 00000020215 13175112471 024045 0ustar00mpegmpeg000000 000000 /* * fractal_rendering_parameters.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal_rendering_parameters.h * \brief Header file related to rendering parameters. * \author Marc Pegon */ #ifndef __FRACTAL_RENDERING_PARAMETERS_H__ #define __FRACTAL_RENDERING_PARAMETERS_H__ #include "color.h" #include "gradient.h" #include "float_precision.h" #include "fractal_addend_function.h" #include "fractal_coloring.h" #include "fractal_iteration_count.h" #include "fractal_transfer_function.h" #include #ifdef __cplusplus extern "C" { #endif /** * \struct RenderingParameters * \brief Structure for handling fractal rendering parameters. */ /** * \typedef RenderingParameters * \brief Convenient typedef for struct RenderingParameters. */ typedef struct RenderingParameters { uint_fast8_t bytesPerComponent; /*!< Bytes per component matching gradient colors'.*/ Color spaceColor; /*!< Fractal space color.*/ IterationCount iterationCount; /*!< Fractal iteration count enum value.*/ ColoringMethod coloringMethod; /*!< Fractal coloring method.*/ AddendFunction addendFunction; /*!< Fractal addend function (used only for average coloring method).*/ uint_fast32_t stripeDensity; /*!< Stripe density (used only for AF_STRIPE addend function).*/ InterpolationMethod interpolationMethod; /*!< Fractal interpolation method (used only for average coloring method).*/ TransferFunction transferFunction; /*!< Fractal transfer function enum value (to make the values fit the gradient better).*/ TransferFunctionPtr transferFunctionPtr; /*!< Transfer function ptr.*/ double multiplier; /*!< Value with which fractal values will be multiplied (to make the values fit the gradient better).*/ double offset; /*!< Offset for mapping value to gradient.*/ Gradient gradient; /*!< Gradient for mapping float values to colors.*/ /* For internal use.*/ double realMultiplier; /*!< Real multiplier (scaled according to gradient size).*/ double realOffset; /*!< Real offset (scaled according to gradient size).*/ } RenderingParameters; /** * \fn void InitRenderingParameters(RenderingParameters *param, uint_fast8_t bytesPerComponent, Color spaceColor, IterationCount iterationCount, ColoringMethod coloringMethod, AddendFunction addendFunction, uint_fast32_t stripeDensity, InterpolationMethod interpolationMethod, TransferFunction transferFunction, double multiplier, double offset, Gradient gradient) * \brief Initialize rendering parameters. * * Bytes per component *must* agree with space color and gradient colors : * this is *not* checked by the function.\n * Gradient will be owned by rendering parameters, and free'd when * rendering parameters are free'd. * * \param param Pointer to structure to initialize. * \param bytesPerComponent Bytes per component for colors of rendering. * \param spaceColor The color for fractal space. * \param iterationCount Fractal iteration count. * \param coloringMethod Fractal coloring method. * \param addendFunction Fractal addend function (used only for average coloring method). * \param stripeDensity Stripe density (used only for AF_STRIPE addend function). * \param interpolationMethod Fractal interpolation method (used only for average coloring method). * \param transferFunction Fractal transfer function (to make the values fit the gradient better). * \param multiplier Value with which fractal values will be multiplied (to make the values fit the gradient better). * \param offset Offset for mapping value to gradient. * \param gradient Gradient for mapping float values to colors. */ void InitRenderingParameters(RenderingParameters *param, uint_fast8_t bytesPerComponent, Color spaceColor, IterationCount iterationCount, ColoringMethod coloringMethod, AddendFunction addendFunction, uint_fast32_t stripeDensity, InterpolationMethod interpolationMethod, TransferFunction transferFunction, double multiplier, double offset, Gradient gradient); /** * \fn RenderingParameters CopyRenderingParameters(const RenderingParameters *render) * \brief Copy rendering parameters. * * \param render Pointer to rendering parameters to copy. * \return Copy of rendering parameters. */ RenderingParameters CopyRenderingParameters(const RenderingParameters *param); /** * \fn void ResetGradient(RenderingParameters *param, Gradient gradient) * \brief Reset gradient. * * Gradient will be owned by rendering parameters, and will be free'd * when rendering parameters are free'd. * * \param param Rendering parameters to be changed. * \param gradient New Gradient. */ void ResetGradient(RenderingParameters *param, Gradient gradient); /** * \fn int isSupportedRenderingFile(const char *fileName) * \brief Check whether a file is a supported rendering file. * * \param fileName File name. * \return 1 if file is a supported rendering file, 0 otherwise. */ int isSupportedRenderingFile(const char *fileName); /** * \fn int ReadRenderingFileBody(RenderingParameters *param, const char *fileName, FILE *file, const char *format) * \brief Read fractal rendering parameters from rendering file body. * * The body of a rendering file is everything that comes after * the format version.\n * fileName is used only for error messages.\n * This function should only be used internally by the library. * * \param param Pointer to the rendering parameters structure to create. * \param fileName Rendering file name. * \param file Pointer to opened file, positioned at the beginning of the body. * \param format Rendering file format. * \return 0 in case of success, 1 in case of failure. */ int ReadRenderingFileBody(RenderingParameters *param, const char *fileName, FILE *file, const char *format); /** * \fn int ReadRenderingFile(RenderingParameters *param, const char *fileName) * \brief Read and parse fractal rendering parameters file. * * \param param Pointer to the structure to store rendering parameters. * \param fileName Rendering file name. * \return 0 in case of success, 1 in case of failure. */ int ReadRenderingFile(RenderingParameters *param, const char *fileName); /** * \fn int WriteRenderingFileBody(const RenderingParameters *param, const char *fileName, FILE *file, const char *format) * \brief Write rendering parameters into file. * * The body of a rendering file is everything that comes after * the format version.\n * fileName is used only for error messages.\n * This function should only be used internally by the library. * * \param param Rendering parameters to write. * \param fileName Rendering file name. * \param file Pointer to opened file, positioned at the beginning of the body. * \param format Rendering file format. * \return 0 in case of success, 1 in case of failure. */ int WriteRenderingFileBody(const RenderingParameters *param, const char *fileName, FILE *file, const char *format); /** * \fn int WriteRenderingFile(const RenderingParameters *param, const char *fileName) * \brief Write rendering parameters into file. * * \param param Rendering parameters to write. * \param fileName Rendering file name. * \return 0 in case of success, 1 in case of failure. */ int WriteRenderingFile(const RenderingParameters *param, const char *fileName); /** * \fn void FreeRenderingParameters(RenderingParameters param) * \brief Free a RenderingParameters structure. * * \param param RenderingParameters structure to be freed. */ void FreeRenderingParameters(RenderingParameters param); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/lib/src/c99_complex_wrapper.c000664 001750 001750 00000004026 13175112471 021205 0ustar00mpegmpeg000000 000000 /* * c99_complex_wrapper.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "c99_complex_wrapper.h" #include #ifdef BUILD_CIPOW #undef BUILD_CIPOW #endif #define BUILD_CIPOW(type, suffix) \ type complex cipow##suffix(type complex x, uint_fast32_t y)\ {\ type complex res;\ \ if (y == 0) {\ res = 1;;\ }\ \ type complex rem = 1;\ res = x;\ while (y > 1) {\ if (y % 2) {\ rem *= res;\ --y;\ }\ y >>= 1;\ res *= res;\ }\ \ res *= rem;\ \ return res;\ }\ \ BUILD_CIPOW(float, f) BUILD_CIPOW(double, ) BUILD_CIPOW(long double, l) #undef BUILD_CIPOW #ifdef BUILD_CNORM #undef BUILD_CNORM #endif #define BUILD_CNORM(type, suffix) \ type cnorm##suffix(type complex x)\ {\ return creal##suffix(x)*creal##suffix(x)+cimag##suffix(x)*cimag##suffix(x);\ }\ \ BUILD_CNORM(float, f) BUILD_CNORM(double, ) BUILD_CNORM(long double, l) #undef BUILD_CNORM #ifdef BUILD_CISINTEGER #undef BUILD_CISINTEGER #endif #define BUILD_CISINTEGER(type, suffix) \ int cisinteger##suffix(type complex x)\ {\ if (cimag##suffix(x) != 0) {\ return 0;\ } else {\ type fptr, iptr;\ fptr = modf##suffix(creal##suffix(x), &iptr);\ \ return (fptr == 0);\ }\ } BUILD_CISINTEGER(float, f) BUILD_CISINTEGER(double, ) BUILD_CISINTEGER(long double, l) #undef BUILD_CISINTEGER fractalnow-0.8.2/lib/src/file_io.c000664 001750 001750 00000007216 13175115345 016727 0ustar00mpegmpeg000000 000000 /* * file_io.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "file_io.h" #include "error.h" #include #include #ifdef _ENABLE_MP_FLOATS #include #include #endif int readString(FILE *file, char *dst) { return fscanf(file, "%s", dst); } int readUint32(FILE *file, uint32_t *dst) { int res; int64_t read; if ((res = fscanf(file,"%"SCNd64,&read)) < 1) { return res; } if (read < 0) { return 0; } *dst = (uint32_t)read; return res; } int readDouble(FILE *file, double *dst) { return fscanf(file,"%lf",dst); } #ifdef _ENABLE_MP_FLOATS static inline int readMPFR(FILE *file, mpfr_t dst) { return (mpfr_inp_str(dst, file, 10, MPFR_RNDN) == 0) ? -1 : 1; } #endif int readBiggestFloat(FILE *file, BiggestFloat *dst) { #ifdef _ENABLE_MP_FLOATS return readMPFR(file, *dst); #else // #ifndef _ENABLE_MP_FLOATS double tmp; int res = readDouble(file, &tmp); if (res > 0) { fromDoubleBiggestF(*dst, tmp); } return res; #endif } int readColor(FILE *file, int_fast8_t bytesPerComponent, Color *dst) { uint32_t color32; uint64_t color64; int res; switch (bytesPerComponent) { case 1: if ((res = fscanf(file,"%"SCNx32,&color32)) < 1) { break; } *dst = ColorFromUint32(color32); break; case 2: if ((res = fscanf(file,"%"SCNx64,&color64)) < 1) { break; } *dst = ColorFromUint64((uint64_t)color64); break; default: FractalNow_error("Invalid bytes per component.\n"); break; } return res; } int writeString(FILE *file, const char *src, const char *suffix) { return fprintf(file, "%s%s", src, suffix); } int writeUint32(FILE *file, uint32_t src, const char *suffix) { return fprintf(file, "%"PRIu32"%s", src, suffix); } int writeDouble(FILE *file, const double src, const char *suffix) { /* We use %G instead of %lG because: * -both are acceptable for printing doubles * (floats are actually promoted to doubles) * -some implementations of printf do not accept * %lG (like Windows') */ return fprintf(file, "%.*G%s", DBL_DIG, src, suffix); } #ifdef _ENABLE_MP_FLOATS static inline int writeMPFR(FILE *file, const mpfr_t src, const char *suffix) { return mpfr_fprintf(file, "%RE%s", src, suffix); } #endif int writeBiggestFloat(FILE *file, const BiggestFloat src, const char *suffix) { #ifdef _ENABLE_MP_FLOATS return writeMPFR(file, src, suffix); #else // #ifndef _ENABLE_MP_FLOATS return writeDouble(file, src, suffix); #endif } int writeColor(FILE *file, Color src, const char *suffix) { uint32_t color32; uint64_t color64; int res; switch (src.bytesPerComponent) { case 1: color32 = ARGB8_TO_UINT32(0, src.r, src.g, src.b); res = fprintf(file, "0x%"PRIx32"%s", color32, suffix); break; case 2: color64 = ARGB16_TO_UINT64(0, src.r, src.g, src.b); res = fprintf(file, "0x%"PRIx64"%s", color64, suffix); break; default: FractalNow_error("Invalid bytes per component.\n"); break; } return res; } fractalnow-0.8.2/gui/src/000775 001750 001750 00000000000 13175145365 015172 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/lib/src/fractal_compute_engine.c000664 001750 001750 00000031774 13175115345 022024 0ustar00mpegmpeg000000 000000 /* * fractal_compute_engine.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "float_precision.h" #include "fractal_compute_engine.h" #include "fractal_coloring.h" #include "fractal_formula.h" #include "fractal.h" #include "fractal_rendering_parameters.h" #include "macro_build_fractals.h" #include "misc.h" #include #define BUILD_FRACTAL_ENGINE(formula,ptype,coloring,iterationcount,addend,interpolation,fprec) \ struct FractalEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec {\ FLOATTYPE(FP_##fprec) centerX;\ FLOATTYPE(FP_##fprec) centerY;\ FLOATTYPE(FP_##fprec) spanX;\ FLOATTYPE(FP_##fprec) spanY;\ FLOATTYPE(FP_##fprec) x1;\ FLOATTYPE(FP_##fprec) y1;\ uint_fast32_t n;\ COMPLEX_FLOATTYPE(FP_##fprec) pixel;\ FLOATTYPE(FP_##fprec) rePixel;\ FLOATTYPE(FP_##fprec) imPixel;\ COMPLEX_FLOATTYPE(FP_##fprec) z;\ COMPLEX_FLOATTYPE(FP_##fprec) c;\ FLOATTYPE(FP_##fprec) res;\ FLOATTYPE(FP_##fprec) normZ;\ FLOATTYPE(FP_##fprec) escapeRadius;\ FLOATTYPE(FP_##fprec) escapeRadius2;\ COMPLEX_FLOATTYPE(FP_##fprec) fractalP;\ uint_fast32_t fractalP_INT;\ COMPLEX_FLOATTYPE(FP_##fprec) fractalC;\ ENGINE_DECL_VAR_FRAC_##formula(FP_##fprec)\ ENGINE_DECL_VAR_CM_##coloring(IC_##iterationcount,AF_##addend,IM_##interpolation,FP_##fprec)\ };\ \ CacheEntry FractalLoop##formula##ptype##coloring##iterationcount##addend##interpolation##fprec(\ void *engData, const Fractal *fractal, const RenderingParameters *render,\ uint_fast32_t x, uint_fast32_t y,\ uint_fast32_t width, uint_fast32_t height)\ {\ struct FractalEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec *data =\ (struct FractalEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec *)engData;\ UNUSED(render);\ \ CacheEntry dres;\ fromUiF(FP_##fprec, data->rePixel, x);\ add_dF(FP_##fprec, data->rePixel, data->rePixel, 0.5);\ mulF(FP_##fprec, data->rePixel, data->rePixel, data->spanX);\ div_uiF(FP_##fprec, data->rePixel, data->rePixel, width);\ addF(FP_##fprec, data->rePixel, data->rePixel, data->x1);\ \ fromUiF(FP_##fprec, data->imPixel, y);\ add_dF(FP_##fprec, data->imPixel, data->imPixel, 0.5);\ mulF(FP_##fprec, data->imPixel, data->imPixel, data->spanY);\ div_uiF(FP_##fprec, data->imPixel, data->imPixel, height);\ addF(FP_##fprec, data->imPixel, data->imPixel, data->y1);\ cfromReImF(FP_##fprec,data->pixel,data->rePixel,data->imPixel);\ cfromUiF(FP_##fprec,data->z, 0);\ cfromUiF(FP_##fprec,data->c, 0);\ fromUiF(FP_##fprec,data->res,0);\ fromUiF(FP_##fprec,data->normZ,0);\ LOOP_INIT_FRAC_##formula(FP_##fprec)\ LOOP_INIT_CM_##coloring(IC_##iterationcount,AF_##addend,IM_##interpolation,FP_##fprec)\ for (data->n=0; data->nmaxIter && \ cmpF(FP_##fprec,data->normZ,data->escapeRadius2) < 0; ++data->n) {\ LOOP_ITERATION_CM_##coloring(IC_##iterationcount,AF_##addend,IM_##interpolation,FP_##fprec)\ LOOP_ITERATION_FRAC_##formula(ptype,FP_##fprec)\ cnormF(FP_##fprec,data->normZ,data->z);\ }\ /* Color even the last iteration, when |z| becomes > escape radius */\ LOOP_ITERATION_CM_##coloring(IC_##iterationcount,AF_##addend,IM_##interpolation,FP_##fprec)\ dres.floatPrecision = FP_##fprec;\ initF(FP_##fprec, dres.x.val_FP_##fprec);\ initF(FP_##fprec, dres.y.val_FP_##fprec);\ crealF(FP_##fprec, dres.x.val_FP_##fprec, data->pixel);\ cimagF(FP_##fprec, dres.y.val_FP_##fprec, data->pixel);\ if (cmpF(FP_##fprec,data->normZ,data->escapeRadius2) < 0) {\ dres.value = -1;\ } else {\ LOOP_END_CM_##coloring(IC_##iterationcount,AF_##addend,IM_##interpolation,FP_##fprec)\ dres.value = toDoubleF(FP_##fprec,data->res);\ }\ return dres;\ }\ \ void FreeEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec(void *engData)\ {\ struct FractalEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec *data =\ (struct FractalEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec *)engData;\ UNUSED(data);\ \ clearF(FP_##fprec, data->centerX);\ clearF(FP_##fprec, data->centerY);\ clearF(FP_##fprec, data->spanX);\ clearF(FP_##fprec, data->spanY);\ clearF(FP_##fprec, data->x1);\ clearF(FP_##fprec, data->y1);\ cclearF(FP_##fprec, data->pixel);\ clearF(FP_##fprec, data->rePixel);\ clearF(FP_##fprec, data->imPixel);\ cclearF(FP_##fprec, data->z);\ cclearF(FP_##fprec, data->c);\ clearF(FP_##fprec, data->res);\ clearF(FP_##fprec, data->normZ);\ clearF(FP_##fprec, data->escapeRadius);\ clearF(FP_##fprec, data->escapeRadius2);\ cclearF(FP_##fprec, data->fractalP);\ cclearF(FP_##fprec, data->fractalC);\ ENGINE_CLEAR_VAR_FRAC_##formula(FP_##fprec)\ ENGINE_CLEAR_VAR_CM_##coloring(IC_##iterationcount,AF_##addend,IM_##interpolation,FP_##fprec)\ }\ \ void InitEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec(\ const Fractal *fractal, const RenderingParameters *render, FractalEngine *engine)\ {\ UNUSED(render);\ engine->fractalLoop = FractalLoop##formula##ptype##coloring##iterationcount##addend##interpolation##fprec;\ engine->freeEngineData = FreeEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec;\ engine->data = (struct FractalEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec *)\ safeMalloc("fractal engine",\ sizeof(struct FractalEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec));\ struct FractalEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec *data =\ (struct FractalEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec *)engine->data;\ UNUSED(data);\ \ initF(FP_##fprec, data->centerX);\ initF(FP_##fprec, data->centerY);\ initF(FP_##fprec, data->spanX);\ initF(FP_##fprec, data->spanY);\ initF(FP_##fprec, data->x1);\ initF(FP_##fprec, data->y1);\ cinitF(FP_##fprec, data->pixel);\ initF(FP_##fprec, data->rePixel);\ initF(FP_##fprec, data->imPixel);\ cinitF(FP_##fprec, data->z);\ cinitF(FP_##fprec, data->c);\ initF(FP_##fprec, data->res);\ initF(FP_##fprec, data->normZ);\ initF(FP_##fprec, data->escapeRadius);\ initF(FP_##fprec, data->escapeRadius2);\ cinitF(FP_##fprec, data->fractalP);\ cinitF(FP_##fprec, data->fractalC);\ fromBiggestF(FP_##fprec, data->centerX, fractal->centerX);\ fromBiggestF(FP_##fprec, data->centerY, fractal->centerY);\ fromBiggestF(FP_##fprec, data->spanX, fractal->spanX);\ fromBiggestF(FP_##fprec, data->spanY, fractal->spanY);\ fromBiggestF(FP_##fprec, data->x1, fractal->x1);\ fromBiggestF(FP_##fprec, data->y1, fractal->y1);\ fromDoubleF(FP_##fprec, data->escapeRadius, fractal->escapeRadius);\ mulF(FP_##fprec, data->escapeRadius2, data->escapeRadius, data->escapeRadius);\ cfromBiggestF(FP_##fprec, data->fractalP, fractal->p);\ cfromBiggestF(FP_##fprec, data->fractalC, fractal->c);\ data->fractalP_INT = (uint_fast32_t)creal_(ctoCDoubleF(FP_##fprec, data->fractalP));\ ENGINE_INIT_VAR_FRAC_##formula(FP_##fprec)\ ENGINE_INIT_VAR_CM_##coloring(IC_##iterationcount,AF_##addend,IM_##interpolation,FP_##fprec)\ } #undef MACRO_BUILD_FRACTAL /* All this crap to avoid creating duplicates of fractal engines: Indeed, with CM_ITERATIONCOUNT coloring method, addend function and interpolation methods are not used : we generate only one fractal engine for all interpolation methods and addend functions (for AF_TRIANGLEINEQUALITY and IM_NONE). The same thing applies with CM_AVERAGECOLORING color methods, where iteration count is not used : we generate only one fractal engine for all iteration counts. It is necessary to reduce executable size... When we are able to compile loops at runtime we won't need all these macros.*/ #define BUILD_FRACTAL_ENGINE_CM_ITERATIONCOUNT_AF_TRIANGLEINEQUALITY_IM_NONE(formula,ptype,iterationcount,fprec) \ BUILD_FRACTAL_ENGINE(formula,ptype,ITERATIONCOUNT,iterationcount,TRIANGLEINEQUALITY,NONE,fprec) #define BUILD_FRACTAL_ENGINE_CM_ITERATIONCOUNT_AF_TRIANGLEINEQUALITY_IM_LINEAR(formula,ptype,iterationcount,fprec) #define BUILD_FRACTAL_ENGINE_CM_ITERATIONCOUNT_AF_TRIANGLEINEQUALITY_IM_SPLINE(formula,ptype,iterationcount,fprec) #define BUILD_FRACTAL_ENGINE_CM_ITERATIONCOUNT_AF_TRIANGLEINEQUALITY(formula,ptype,iterationcount,interpolation,fprec) \ BUILD_FRACTAL_ENGINE_CM_ITERATIONCOUNT_AF_TRIANGLEINEQUALITY_IM_##interpolation(\ formula,ptype,iterationcount,fprec) #define BUILD_FRACTAL_ENGINE_CM_ITERATIONCOUNT_AF_CURVATURE(formula,ptype,iterationcount,interpolation,fprec) #define BUILD_FRACTAL_ENGINE_CM_ITERATIONCOUNT_AF_STRIPE(formula,ptype,iterationcount,interpolation,fprec) #define BUILD_FRACTAL_ENGINE_CM_ITERATIONCOUNT(formula,ptype,coloring,iterationcount,addend,interpolation,fprec) \ BUILD_FRACTAL_ENGINE_CM_ITERATIONCOUNT_AF_##addend(formula,ptype,iterationcount,interpolation,fprec) #define BUILD_FRACTAL_ENGINE_CM_AVERAGECOLORING_IC_DISCRETE(formula,ptype,addend,interpolation,fprec) \ BUILD_FRACTAL_ENGINE(formula,ptype,AVERAGECOLORING,DISCRETE,addend,interpolation,fprec) #define BUILD_FRACTAL_ENGINE_CM_AVERAGECOLORING_IC_CONTINUOUS(formula,ptype,addend,interpolation,fprec) #define BUILD_FRACTAL_ENGINE_CM_AVERAGECOLORING_IC_SMOOTH(formula,ptype,addend,interpolation,fprec) #define BUILD_FRACTAL_ENGINE_CM_AVERAGECOLORING(formula,ptype,coloring,iterationcount,addend,interpolation,fprec) \ BUILD_FRACTAL_ENGINE_CM_AVERAGECOLORING_IC_##iterationcount(formula,ptype,addend,interpolation,fprec) #define MACRO_BUILD_FRACTAL(formula,ptype,coloring,iterationcount,addend,interpolation,fprec) \ BUILD_FRACTAL_ENGINE_CM_##coloring(formula,ptype,coloring,iterationcount,addend,interpolation,fprec) MACRO_BUILD_FRACTALS /* Build CreateEngine function. */ #define VAL_PINT 1 #define VAL_PFLOATT 0 /*#define BUILD_InitEngine(formula,ptype,coloring,iterationcount,addend,interpolation,fprec) \ if (fractal->fractalFormula == FRAC_##formula && \ biggestComplexFloatIsInteger(fractal->p) == VAL_##ptype && \ render->coloringMethod == CM_##coloring && render->iterationCount == IC_##iterationcount && \ render->addendFunction == AF_##addend && render->interpolationMethod == IM_##interpolation && \ floatPrecision == FP_##fprec) {\ \ InitEngine##formula##ptype##coloring##iterationcount##addend##interpolation##fprec(\ fractal,render,engine);\ return;\ }*/ #define BUILD_InitEngine_CM_ITERATIONCOUNT(formula,ptype,iterationcount,addend,interpolation,fprec)\ if (render->coloringMethod == CM_ITERATIONCOUNT && fractal->fractalFormula == FRAC_##formula && \ cisintegerBiggestF(fractal->p) == VAL_##ptype && \ render->iterationCount == IC_##iterationcount && floatPrecision == FP_##fprec) {\ \ InitEngine##formula##ptype##ITERATIONCOUNT##iterationcount##TRIANGLEINEQUALITY##NONE##fprec(\ fractal,render,engine);\ goto end;\ } #define BUILD_InitEngine_CM_AVERAGECOLORING(formula,ptype,iterationcount,addend,interpolation,fprec)\ if (render->coloringMethod == CM_AVERAGECOLORING && fractal->fractalFormula == FRAC_##formula && \ cisintegerBiggestF(fractal->p) == VAL_##ptype && render->addendFunction == AF_##addend && \ render->interpolationMethod == IM_##interpolation && floatPrecision == FP_##fprec) {\ \ InitEngine##formula##ptype##AVERAGECOLORING##DISCRETE##addend##interpolation##fprec(\ fractal,render,engine);\ goto end;\ } #define BUILD_InitEngine(formula,ptype,coloring,iterationcount,addend,interpolation,fprec) \ BUILD_InitEngine_CM_##coloring(formula,ptype,iterationcount,addend,interpolation,fprec) #undef MACRO_BUILD_FRACTAL #define MACRO_BUILD_FRACTAL(formula,ptype,coloring,iterationcount,addend,interpolation,fprec) \ BUILD_InitEngine(formula,ptype,coloring,iterationcount,addend,interpolation,fprec) int CreateFractalEngine(FractalEngine *engine, const Fractal *fractal, const RenderingParameters *render, FloatPrecision floatPrecision) { int res = 0; MACRO_BUILD_FRACTALS /* This should never happen, because fractal engine is built by macros for all possible * values of each parameter. */ FractalNow_werror("Could not create fractal compute engine for given parameters.\n"); end: return res; } void FreeFractalEngine(FractalEngine *engine) { engine->freeEngineData(engine->data); free(engine->data); } CacheEntry RunFractalEngine(const FractalEngine *engine, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t x, uint_fast32_t y, uint_fast32_t width, uint_fast32_t height) { return engine->fractalLoop(engine->data, fractal, render, x, y, width, height); } fractalnow-0.8.2/lib/include/file_io.h000664 001750 001750 00000012022 13175115345 017557 0ustar00mpegmpeg000000 000000 /* * file_io.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file file_io.h * \brief Header file related to file IO. * \author Marc Pegon */ #ifndef __FILE_IO_H__ #define __FILE_IO_H__ #include "color.h" #include "float_precision.h" #include #include #ifdef __cplusplus extern "C" { #endif /** * \fn int readString(FILE *file, char *dst) * \brief Read string from file. * * \param file File from which to read string. * \param dst Destination string. * \return Number of elements successfully read or EOF (like fscanf). */ int readString(FILE *file, char *dst); /** * \fn int readUint32(FILE *file, uint32_t *dst) * \brief Read uint32 from file. * * \param file File from which to read uint32. * \param dst Destination uint32. * \return Number of elements successfully read or EOF (like fscanf). */ int readUint32(FILE *file, uint32_t *dst); /** * \fn int readDouble(FILE *file, double *dst) * \brief Read double from file. * * \param file File from which to read long double. * \param dst Destination double. * \return Number of elements successfully read or EOF (like fscanf). */ int readDouble(FILE *file, double *dst); /** * \fn int readBiggestFloat(FILE *file, BiggestFloat *dst) * \brief Read BiggestFloat from file. * * \param file File from which to read float. * \param dst Destination. * \return Number of elements successfully read or EOF (like fscanf). */ int readBiggestFloat(FILE *file, BiggestFloat *dst); /** * \fn int readColor(FILE *file, int_fast8_t bytesPerComponent, Color *dst) * \brief Read color from file as a hexadecimal number. * * Exit program with error if bytesPerComponent is not 1 or 2. * * \param file File from which to read color. * \param bytesPerComponent Bytes per component for color to read (either 1 for RGB8 or 2 for RGB16). * \param dst Destination color. * \return Number of elements successfully read or EOF (like fscanf). */ int readColor(FILE *file, int_fast8_t bytesPerComponent, Color *dst); /** * \fn int writeString(FILE *file, const char *src, const char *suffix) * \brief Write string into file. * * \param file File to write into. * \param src Source string. * \param suffix Suffix to add after source string. * \return Number of characters written, negative in case of error (like fprintf). */ int writeString(FILE *file, const char *src, const char *suffix); /** * \fn int writeUint32(FILE *file, uint32_t src, const char *suffix) * \brief Write uint32 into file. * * \param file File to write into. * \param src Source uint32. * \param suffix Suffix to add after uint32. * \return Number of characters written, negative in case of error (like fprintf). */ int writeUint32(FILE *file, uint32_t src, const char *suffix); /** * \fn int writeDouble(FILE *file, double src, const char *suffix) * \brief Write double into file. * * \param file File to write into. * \param src Source double. * \param suffix Suffix to add after double. * \return Number of characters written, negative in case of error (like fprintf). */ int writeDouble(FILE *file, const double src, const char *suffix); /** * \fn int writeBiggestFloat(FILE *file, const BiggestFloat src, const char *suffix) * \brief Write BiggestFloat into file. * * \param file File to write into. * \param src Source float. * \param suffix Suffix to add after float. * \return Number of characters written, negative in case of error (like fprintf). */ int writeBiggestFloat(FILE *file, const BiggestFloat src, const char *suffix); /** * \fn int writeBiggestFloat(FILE *file, cBiggestFloat *dst) * \brief Read BiggestFloat from file. * * \param file File from which to read float. * \param dst Destination. * \return Number of elements successfully read or EOF (like fscanf). */ int readBiggestFloat(FILE *file, BiggestFloat *dst); /** * \fn int writeColor(FILE *file, Color src, const char *suffix) * \brief Write color into file as a hexadecimal number. * * Exit program with error if color bytesPerComponent is not 1 or 2. * \param file File to write into. * \param src Source color. * \param suffix Suffix to add after source color. * \return Number of characters written, negative in case of error (like fprintf). */ int writeColor(FILE *file, Color src, const char *suffix); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/config_files/config19.config000664 001750 001750 00000000224 13175112471 022660 0ustar00mpegmpeg000000 000000 C075 MANDELBROT -0.7 0 3. 3. 1E30 250 1 0x0 AVERAGECOLORING CURVATURE LINEAR IDENTITY 0.5 0 0 0xFF 0.25 0xFFFFFF 0.5 0xFFFF00 0.75 0xFF0000 1 0xFF fractalnow-0.8.2/examples/config_files/config08.config000664 001750 001750 00000000261 13175112471 022657 0ustar00mpegmpeg000000 000000 c075 julia 0.285 0.01 0 0 2.47464114832536 2.47464114832536 10000000 1000 1 0x0 iterationcount smooth identity 0.01 0 0 0x39a0 0.25 0xffffff 0.5 0xfffe43 0.75 0xbf0800 1 0x39a0 fractalnow-0.8.2/gui/include/mpfr_spin_box.h000664 001750 001750 00000005227 13175112471 021042 0ustar00mpegmpeg000000 000000 /* * mpfr_spin_box.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file mpfr_spin_box.h * \brief Header file introducing MPFRSpinBox class. * * \author Marc Pegon */ #ifndef __MPFR_SPIN_BOX_H__ #define __MPFR_SPIN_BOX_H__ #include #include class MPFRSpinBox : public QAbstractSpinBox { Q_OBJECT public: MPFRSpinBox(QWidget * parent = 0); ~MPFRSpinBox(); enum Notation { ClassicNotation = 0, ScientificNotation }; void fixup ( QString & input ) const; void stepBy(int step); const mpfr_t *value(); long double value_d(); void setMaximum ( const mpfr_t * max ); void setMinimum ( const mpfr_t * min ); void setRange ( const mpfr_t * min, const mpfr_t * max); void setMaximum ( long double max ); void setMinimum ( long double min ); void setRange ( long double min, long double max); void setSingleStep ( const mpfr_t * val ); void setSingleStep ( long double val ); void setNotation ( Notation notation ); void setDecimals ( int prec ); /* Checks that the str can be converted to a long */ QValidator::State validate ( QString & input, int & pos ) const; protected: QAbstractSpinBox::StepEnabled stepEnabled() const; virtual mpfr_t *valueFromText(const QString &text) const; virtual QString textFromValue(const mpfr_t *val) const; protected: mpfr_t m_value; mpfr_t m_singleStep; mpfr_t m_minimum; mpfr_t m_maximum; Notation m_notation; int m_decimals; private: void updateText(); inline bool isInRange(const mpfr_t val) const; void aux_setValue(const mpfr_t *val); void setValue(const mpfr_t *val, bool updateText); void aux_setValue(long double val); void aux_setMinimum(); void aux_setMaximum(); public slots: void setValue(const mpfr_t *val); void setValue(long double val); private slots: void onTextEdited(const QString & text); void onEditingFinished(); signals: void valueChanged ( const mpfr_t *val ); }; #endif fractalnow-0.8.2/lib/src/thread.c000664 001750 001750 00000015140 13175112471 016560 0ustar00mpegmpeg000000 000000 /* * thread.c -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "thread.h" #include "error.h" #include "fractalnow.h" #include "misc.h" #include #include #ifdef _ENABLE_MP_FLOATS #include #include #endif void *StartThreadRoutine(void *arg); Threads *CreateThreads(uint_fast32_t N) { Threads *res = (Threads *)safeMalloc("threads", sizeof(Threads)); res->thread = (pthread_t *)safeMalloc("pthreads", N*sizeof(pthread_t)); res->startThreadArg = (StartThreadArg *)safeMalloc("startThreadArgs", N*sizeof(StartThreadArg)); res->lastResult = (void **)safeMalloc("last results", N*sizeof(void *)); res->N = N; safePThreadMutexInit(&res->startThreadCondMutex, NULL); safePThreadCondInit(&res->startThreadCond, NULL); safePThreadMutexInit(&res->threadsMutex, NULL); safePThreadCondInit(&res->allThreadsReadyCond, NULL); safePThreadMutexLock(&res->threadsMutex); safePThreadCondInit(&res->allPausedCond, NULL); safePThreadCondInit(&res->allResumedCond, NULL); safePThreadCondInit(&res->resumeTaskCond, NULL); res->nbReady = 0; res->nbPaused = 0; for (uint_fast32_t i = 0; i < N; ++i) { res->startThreadArg[i].threadId = i; res->startThreadArg[i].threads = res; res->startThreadArg[i].message = NULL; res->startThreadArg[i].startRoutine = NULL; res->startThreadArg[i].arg = NULL; res->startThreadArg[i].result = &res->lastResult[i]; safePThreadCreate(&(res->thread[i]),NULL,StartThreadRoutine,&res->startThreadArg[i]); } /* Wait till all threads are ready before returning. */ safePThreadCondWait(&res->allThreadsReadyCond, &res->threadsMutex); safePThreadMutexUnlock(&res->threadsMutex); return res; } void *StartThreadRoutine(void *arg) { #ifdef _ENABLE_MP_FLOATS mpfr_set_default_prec((mpfr_prec_t)fractalnow_mp_precision); #endif StartThreadArg *startThreadArg = (StartThreadArg *)arg; Threads *threads = startThreadArg->threads; do { safePThreadMutexLock(&threads->startThreadCondMutex); safePThreadMutexLock(&threads->threadsMutex); ++threads->nbReady; if (threads->nbReady+threads->nbPaused == threads->N) { safePThreadCondSignal(&threads->allPausedCond); } if (startThreadArg->message != NULL) { FractalNow_message(stdout, T_VERBOSE, "%s [%"PRIuFAST32"] : %s.\n", startThreadArg->message, startThreadArg->threadId, *startThreadArg->result == NULL ? "DONE" : "CANCELED"); } if (threads->nbReady == threads->N) { safePThreadCondSignal(&threads->allThreadsReadyCond); } safePThreadMutexUnlock(&threads->threadsMutex); safePThreadCondWait(&threads->startThreadCond, &threads->startThreadCondMutex); safePThreadMutexUnlock(&threads->startThreadCondMutex); if (startThreadArg->startRoutine == NULL) { break; } if (startThreadArg->message != NULL) { FractalNow_message(stdout, T_VERBOSE, "%s [%"PRIuFAST32"]...\n", startThreadArg->message, startThreadArg->threadId); } *(startThreadArg->result) = startThreadArg->startRoutine(startThreadArg->arg); } while (1); #ifdef _ENABLE_MP_FLOATS mpfr_free_cache(); #endif return NULL; } void DestroyThreads(Threads *threads) { uint_fast32_t nbReady = 0; safePThreadMutexLock(&threads->threadsMutex); nbReady = threads->nbReady; if (nbReady < threads->N) { safePThreadCondWait(&threads->allThreadsReadyCond, &threads->threadsMutex); nbReady = threads->nbReady; } safePThreadMutexUnlock(&threads->threadsMutex); safePThreadMutexLock(&threads->startThreadCondMutex); for (uint_fast32_t i = 0; i < threads->N; ++i) { threads->startThreadArg[i].startRoutine = NULL; } safePThreadCondBroadcast(&threads->startThreadCond); safePThreadMutexUnlock(&threads->startThreadCondMutex); void *status; for (uint_fast32_t i = 0; i < threads->N; ++i) { safePThreadJoin(threads->thread[i], &status); if (status != NULL) { FractalNow_message(stderr, T_QUIET, "Thread return value is not as \ expected.\n"); } } safePThreadMutexDestroy(&threads->startThreadCondMutex); safePThreadMutexDestroy(&threads->threadsMutex); safePThreadCondDestroy(&threads->startThreadCond); safePThreadCondDestroy(&threads->allThreadsReadyCond); safePThreadCondDestroy(&threads->allPausedCond); safePThreadCondDestroy(&threads->allResumedCond); safePThreadCondDestroy(&threads->resumeTaskCond); free(threads->thread); free(threads->startThreadArg); free(threads->lastResult); free(threads); } ThreadArgHeader *GetThreadArgHeader(const void *arg) { return *((ThreadArgHeader **)arg); } void *GetThreadArgBody(const void *arg) { return *((void **)(((uint8_t *)arg)+sizeof(ThreadArgHeader *))); } static inline int ReadIntVarSafe(int *variable, pthread_spinlock_t *mutex) { int res; safePThreadSpinLock(mutex); res = *variable; safePThreadSpinUnlock(mutex); return res; } static inline void WriteIntVarSafe(int *variable, int value, pthread_spinlock_t *mutex) { safePThreadSpinLock(mutex); *variable = value; safePThreadSpinUnlock(mutex); } int CancelTaskRequested(ThreadArgHeader *threadArgHeader) { return ReadIntVarSafe(threadArgHeader->cancel, threadArgHeader->cancelMutex); } void SetThreadProgress(ThreadArgHeader *threadArgHeader, int progress) { WriteIntVarSafe(&threadArgHeader->progress, progress, &threadArgHeader->progressMutex); } void HandlePauseRequest(ThreadArgHeader *threadArgHeader) { int pause = ReadIntVarSafe(threadArgHeader->pause, threadArgHeader->pauseMutex); if (pause) { uint_fast32_t nbThreadsActive; Threads *threads = threadArgHeader->threads; safePThreadMutexLock(&threads->threadsMutex); ++threads->nbPaused; nbThreadsActive = threads->N-(*threadArgHeader->nbReady); if (threads->nbPaused == nbThreadsActive) { safePThreadCondSignal(&threads->allPausedCond); } safePThreadCondWait(&threads->resumeTaskCond, &threads->threadsMutex); --threads->nbPaused; if (threads->nbPaused == 0) { safePThreadCondSignal(&threads->allResumedCond); } safePThreadMutexUnlock(&threads->threadsMutex); } } fractalnow-0.8.2/command-line/include/anti_aliasing.h000664 001750 001750 00000004747 13175112471 022564 0ustar00mpegmpeg000000 000000 /* * anti_aliasing.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file anti_aliasing.h * \brief Header file related to anti-aliasing methods. * \author Marc Pegon */ #ifndef __ANTI_ALIASING_H__ #define __ANTI_ALIASING_H__ #include #ifdef __cplusplus extern "C" { #endif /** * \enum e_AntiAliasingMethod * \brief Possible anti-aliasing methods. */ /** * \typedef AntiAliasingMethod * \brief Convenient typedef for enum e_AntiAliasingMethod. */ typedef enum e_AntiAliasingMethod { AAM_NONE = 0, /*!< No anti-aliasing.*/ AAM_GAUSSIANBLUR, /*!< Gaussian Blur.*/ AAM_OVERSAMPLING, /*!< Over sampling (compute a bigger image and scale it down).*/ AAM_ADAPTIVE /*!< Adaptive (compute more than one value for some pixels).*/ } AntiAliasingMethod; /** * \var nbAntiAliasingMethods * \brief Number of anti-aliasing methods. */ extern uint_fast32_t nbAntiAliasingMethods; /** * \var AntiAliasingMethodStr * \brief Strings of anti-aliasing method enum values. */ extern const char *AntiAliasingMethodStr[]; /** * \var AntiAliasingMethodDescStr * \brief More descriptive strings for anti-aliasing methods. */ extern const char *AntiAliasingMethodDescStr[]; /** * \fn AntiAliasingMethod GetAAM(const char *str) * \brief Get anti-aliasing method from string. * * Function is case insensitive. * Possible strings are : * - "none" for AAM_NONE * - "blur" for AAM_GAUSSIANBLUR * - "oversampling" for AAM_OVERSAMPLING * - "adaptive" for AAM_ADAPTIVE * Exit with error in case of failure. * * \param str String specifying anti-aliasing method. * \return Corresponding anti-aliasing method, or AAM_UNKNOWN in case of failure. */ AntiAliasingMethod GetAAM(const char *str); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/config_files/config15.config000664 001750 001750 00000000257 13175112471 022662 0ustar00mpegmpeg000000 000000 C075 JULIA 0.25964774188509 -0.002329242091954 0.0 0.0 3 3 64. 1000 1 0x0 ITERATIONCOUNT SMOOTH IDENTITY 1.6E-2 0 0 0x39A0 0.25 0xFFFFFF 0.5 0xFFFE43 0.75 0xBF0800 1 0x39A0 fractalnow-0.8.2/gui/icons/icon.icns000664 001750 001750 00000264753 13175112471 017335 0ustar00mpegmpeg000000 000000 icnsiic08" jP ftypjp2 jp2 Ojp2hihdrcolr"cdef"Zjp2cOQ2R \@@HHPHHPHHPHHPHHP !S ]@@HHPHHPHHPHHPHHPS ]@@HHPHHPHHPHHPHHPS ]@@HHPHHPHHPHHPHHPz($`T/T/1 ܅jQV9x ^_h.z~ 3z8$`4|GQ.8!XFuf,faL,C y>w@ԿZyB?z(/O,[/=3ΦȪRN@BA^"goXtK4oꝈXl. (;4+OxѰL22³׹9YA_T?IF. k(٣_/#O޶Kt^Y=o3](h®VŰ 3jF-a \a;! /D,6[k_Ѹ2V2{3D7.n5aZޘָQ7|5=H L4K:S8VU{FؑHyaG[ӪmړL~ȉ0\mzF]?KyΰQ<0.fI<ᅫSH ς s`Geܰ!d؉MTcN[ߖ̉R5,t=翜du|ABCUƠ%$D+ <Ϗ 'tTrsh?t2*K-z׺MT*_ez_jowgz4NN%lu$ԇ%ò+;~7u:[Lw<4{Fbw w޳ Uϛ؎+Y`.*-\>XsNX:Wq=кhK(SpS{K#Ͼܟ}}΅ar\`8SGO/ O{$~ʿvTg~V7臈f&zBf8 $`NS 6.0T@3gcL6$؏kd77a@zjdoF?4:uqU|,L1-e+!4u:+y`MjE_lZtܞ/%ܽPH>@aqt^ؐ7/DD}1C~oHR賊xցECBbE06X;}eZD(ެdX$n'X 8 lމp U#348 .hb`*X!3ėeܟ?L?tg XC,dE"3P%7xh=Weaex8ju-¡pU~> Oc~q;zE}8k'_>qQ h,!HqMy9Ϧ&h-CJۍ瘺\ڂT6̯@O&8E/Tz EՒ[DXi=}ɫAj+ )<(5O(١w _Z]GfI=@wFiv\*|D/>ukO+UJISL†_1n_˭􈥂rckDՊ}()vDw*ϜeAn'+VM/Q3F/Q3o`6EfNM}F˕c˜/W&’jͤ\t7Yk!b`},_-PI)sIL%t&}Up3f:{EJaԪ>Yބng[ћ{Q<9 Ug=-eKVL֙2x y[ه#:q) A81Zr!04Q>nDZyZ*K=Erj9pJ̫==j˪=3ȱakt Yʴ? s@]^J%gĔyqkRuDSi0qvJ0zֻiT0N(&@)Kfi+C}K +SA{~"8bK!گYt:.CC} Vp#fMxPejJ { X>NmXrBd8$mw 6VНl7V*zfğ8FfʟϡxsYf,&'\}n7Uo-zxGlg4'2}))Zit{oH`Q:)1;Pz̦p丞QFu#tVnZ$~!aC? 9HjDȼ`IYDA)-\ORȈnДi!vHQ(e缒<_|$CC(H7 dheȻ !Ԟ[$~ګ2D(I[.I3;iOq<2)5qOB7FڦٱnZ}MmIDQ߶Q]]DUN:c*3s{C ;'G: \?vU%߫ *NJmV^3}j/2 >+Z'DfZdƠ%#[1VVMzJGf }.gh,Ǘ!>TM,ڕ"}_Gz'Z61羅2ͯgk}@ =hcEV#/בSYhQ/|lY"{4=uwN*qH,+ In=}ZW>D+ύWLKfeVW4%:G֧(ȯɂԠ-Vd^*ܬLf*5ܣ YNlXdΉLho4 ZM1埯wV\rϘ|pqy3~?i WI}+<s`j :xl=l)8/֑VYt6y#m4ɛǠ&ܚ,O*؃V,TWҳ_qڹf6z]vS@aՒ,PGz+_  pvff٭0j6Џ2x57h ҧ]lTu^FHdjw@(ULp m瀩[|bhOF" a]r ,#ĬV.у4fwpXa|Kc7qB>`c}H:7oB ]B ˉA1oyD}Pdv0qAa\NTKZ2]t.(LK\j!J)A׭wS{Aso9gm /|P U2,-316R2M 3mD>(|:5 )c# z V^X9re&0sn&8Nb5)īrZVh18I3(VN mY]/&Sʼ_íw^\2>8wmż$Jጽ dC;*^{ͩӘ5G+2g)q@ z#5N)tBOg @s]iLkiyIu dr8ʊ۪Nirn⋓!nsT0}wFPb}p4̱>6 D G#Xz`eNTqz!g Ig-e<7Fs]\w'mYElT*;<`d蔳;ݟ pX` =.huj<\<%-=e5h׃\زՔ쥼AA%]+`Z.B+ɥiNbk-ܽHgO>ϥxV)dy@+ܸ֌tsykƒ;= + q'6^ Iw|[i"yr TE$4j$U({jZ,_=rx-ƢT={CxD2vzk~!ܔi!v&NN<./#{Ү0.gOqC85#%xjt%t 6C*G:61~H&3Xϑ"V)̽6uǻ %j5H.II]3$@H Vg yQXY򑉢Vb~n= >ET(lqF.D^Ԕ*q/!lpUw<}uYȱZ̀G."^B R>s>6׸z6Ձʿr+rFqs;P QX@(rt1"Mr׿ #+5Gl?sSN8<lV Z'6ŏ#w|32y3I|ȳH3J*uYdLWd&5Ɯʫ-,unHb3Kg 99\cuJڨxJau*9e`fhq*e Vr*Me 7+g_X5WxrI;ͬ}NJ4f~ e(x^ rŰ}%7YCUBsE%8e Yq+"¹֜4<(a9FW\;ŵqQ,2x6opq/'2e _@Tٷ^X&7xfw N&׆JW8>j_@F&ILGTg5-Qn%imQM+5P1ͥÕ!rDT7CJֈ[ؘK^ŋtwSla\{*^+Lxcs ~(NF96 m!P9t~!Op#7id6ԅg5j= m}M#ME?A!4 gg jrg.aڂ{v95v"Fv(FeVg7쪭Uh=BEl{/nYԶ0%S}!BzFc$h3ԾkJpJά}}<KmIA^gP-`37#jhI*!(r B;70!Y?'<ir׮]kͮ7 Y 0n~4Q$|kaTP~Qw͈LXak7^V+'tCpw+G덗JA/W-.dAfTR{X@Dg'W=^kMR:!32b9GbZbPJM]Ckr3Eq}Gu/ ?lI (8{g,&꜂R58C*h:`ԇJY_΂j":)mGOnyC5<ٛqhv,{ǫRBO1o:)csшpTnOv#%(Ώq_XP VhE'م#o1ZT "ݏET:"VH#mnbڕW3 4G /|׸~3"z̀9%i7(6iZuuL,ٽ/ ^|J]ȧ/d̡ʦ1Rɰ.CK6M`Ej[W̓?æS蠟 xDq7h"EԹ7FY{Pk,32Yt0:xxk?l:QM+d-5nS$z <-6 Z;{"c,} VV@8?^ GP`)>A_[(s\I َoҒk.O i@5o/*d )`כi<pe7ȶ!!L*=!-C=!+ %wd{`paIi1g} 4rfD2-7?*(>6qX뼔un:&N|Nڥ 7~`uJ`YOfVBqŁp-^T3g.\ yn;.&Avdͺ5'[BҌ̒lIf"7S9q Q۰5ɸgJZozfNf#+hhmX0f*>7#!S;/&\jkM2}V#'0m-}ݛɾ/O>e8M kG`dzX#Uf#>jMjUO4II#4ͣd7oz7mwn%,#k( A^U!n\]}3|vDè T8P4lPWitԎ2Ӊs/FXAt_8< z|1`7~ %9FjZV]3F͕5PxS^}5q&V8ͥrpRaYa)/4OpuxV&h呀/;އn-FKSyšJ`r1U,} rPeJbWh,Hʩ!Gx.k!tm8ΏqRbZܔIT͌,ie[|>&\u'>Uނ3N˓<*쩋[}>wS3Qi/woxyBw]~ס9L\k/7N?ƳCqrhgdI74H*DZf,clkG}8-ٿՇ/6!Me =+54AѮᠸ'2NOIƤ8@t3]q-a}а5Sg!ȕA s)/#> [9Zp'sL6pyfrT&kh~0Vex.vB27"A7tEXf?UdfL9NըnPz-^w?fuR8`狫1q&Us$_@j }4ՖE҆`j,=w~%Q m=O:eVgs3kьk3H,CBHt/ueA4"R EuU`6ܜvHŸl1a={tWYK`P*-SB7e`)4ωQ;PJ$GUL:O/ Yn pL0>?5p$m0RW## bVNh uĬ1uѿ}֢˵d󥆀T ˢO"KO_m3l1}`*=Ӂ&Uc@/X7 gi,'nlojXk%Yezr5}3_X]򦷴t-D *^pT&_.R?fh8X'ʻp_2 tڢvV6؏rWI=e:0̫բcKڹ Z%w=vUyЋ/K -lUP+2[!X Ԁbw1:En̐ʫ QG lj~ w3:F_׃Y!ImJʨwv#Z[(l$4^bK;)dwvĎF6S HjMIޅ?7چ]<::_[߯%Ԍ GK^qG^Q@tl5QeL*%m/p6hG[:_`.oq/Nѐ1E(0qBP<?ئ;8}Ss{Gӝm歝Wvl0qKX +6M+@PH3Wr)Gմd$0Ӑw+B ϑ/ ӗ+KCǟ??K3|`?}zO쯒7S{q`t{$+3__ , Z>hBI|9E6A Δ1;j+ 4-i6α4!6f=&Z08K+JOh LYtQ_5gldl2D󞈽ﵞhBKY<AJ`%xH&_?9i DbnԪ?ዢ4A0IQeqTv[}?QnGHzu$wżQ h gA B]FyP5)W.: G{cT| @޺Ro\}! KÔN~n|7>oJkF)Wс"c%tZ k9wSIC̑bm9|i~gةS- OXCw S=6)MW$Vx.x'q8̡iV@A~J48 aH`:"qm$&.,1 LN(8T] ] U>t7)j}hfo G{D雚鱍V#R'>HUn:6 us1M6=Fn EBm]9D嫔w V~zݐpS?.ѱ&AIol5aMfq k? h:F6a UJ9p+$ +RWY=I(M/ttm Wki\rU!2);??*~Vݳe8BWӥ^ b6VڤX4tMiqZĴq > $N39jq1ׅTĉt srokqCtn~ - +O,I$4 Kyi!ũ $2Hr{"R7{&#k{y^ k *hs9^YCb6{:9;t˴ظă^y1UFګ,m>F̟goilFzF۷\C ]6Vby3 Ԅ08T^!!}YĞqҺ,#hrհǒ Y@ZQyJQCq{1bq0yJK&"*S;mpS)֔"B4A9uv[{6׆ItmQ5ǥֺK'`BBkJЯ+$e2 ;ӟhLCڰZ> >@WVWhtzNFRV:lIIYkHJM"BUp4am=/lI*tqi MRڥBQ걪2Q3͛t`@)<ےtC, /ya6<7(V$ޤTҘe& ܶ~X}Gu/XXlҌp\CN.,[X22hZ B:,+*~xIqӷД:$Y^!l5$ S 4Fa/A[& W %O16E3S+)5O OhE{ } !0c:y,%N{Ia%K:J9wV:iѭ uſJQ1ڧΎgRߔ΢-Kُ̒oMnbM {b=/k+/13m@t&~slDh 6s9 ^1%ֈ'/U _?E$Ug^Ԍ&IǛ4*T{ƞK.T-BA?m ʇh#<^vFĻ!j#:+0=(Tc W9]l/#>JOTٽv"i6ٿTmu9߽b(+MN|ʉ<j zZmR$)ZPxe|_ܟ$b ɼ3˺{\]J)t xYcGs"2QC6du+n8VXIx\ۨ*W3"h'F n=(QCl-dp/*\2NC%_.ҺRP(Q?1'ǧ. Bd!oK9,ܻxV!- xFhCw޴kF)9Y n2V$gzdCP#X䜬oBkzI/Qm*CtfNdaMGfhqp!hC80G53904iXת1=׀Q.vjwp:+G0:?id2/kZp4 ECd`"Z@kZvFlZ~HxU#q7anA)$2͖j˥D} .Ppt-կ@Ԉ ިm6I䌨mr]a~/ėy4#~A\uʍ_{j Јf^c]_}$h.&b׹6ZDâ56NPAF.JΠ1/ae3p]LuvNϰƖR{[XRZa{u;5v5$%gtwa8d9ľ?UoH) Gv.y}h,u$2&_V Ffq$zE !Nl7oj"38#.* tɟn&0-8 MC Dޓ#Ԁ_hZ? o^h棥ʀm>3mLD1('eƧ7@赟6x[2Fe" <|sRڂ uz7-yBXlA$f6'Gל!5hڲ*GGx `znl* OoC N4B}҄$wFD A) ^i1Iw][&Wd W%=NqrӲQQ9,y;G4)Ͱcñ~iK2rVYh9:;(uS!z, x&8L] iۿY6XwNh=rȍ &tUKJ^0 1uJ=pnvژv F_Y ]۳PQpiE~QnٍثbT壙rZɈȤu/{[In_ert X]QU?ec<0/3n?0`<#;].L1Pv2ki>&#7 )RsU䠲uSQPw~~U;H"gaj=* hej*Lz@c!nqt:ȀTi_GMC.=,n)KtU8[aG%Pc-=8 C;tO;s⊮[9;KoR>XwAi\ 7_2x}OUpCܑI1>$8X߂q871\fΔc%YAv5NT1Ul:8y|s.KkޢE>-dT çgb-b!{HSŨR-"&G<}dvG4gd@ =UdA Vq񝨔"Ҹ6>MUF)WqȠACl.dܓdq38Y&ə^v>A[zÕ32]vUylFŘ|KtT5^$IY]9IX8;3i&y% 6E!uY"x:ōQ?+ Wnm_XYa@M]=t#WaH@|)=0ߏP @('zPV(mۀ]Y eda4-SΝ:oY>q<£|X-,0t&wSMN( yܚ]@f j gz6e!+ZWK6>DޞҬ^a*}9}z3{)UqrM# ޚYETSH5rDʱF='7n]}fRb%+7hxEG}<~EofmWlg7QmRU^V$Wpդ`]){\ u꾸hE'߫VVE:#>" ׎|*?,#WNkrYж$P?2Vgsh[-Xiw%ߣx.?.s>-'6Q;?]C4tWah%>{4~s{",$YFߵ4g`YμHsP} LOGSߠ|.t$_ |3 E}lhI;t$ҼK7qaGwS)p՝_q[K>- OjyΧ+{qeE5޽[毜6Gqmw:@ؑ*>A~r7@^vo'#L2^h&DU(hҧ|2I!n Q1V.8uϛEH2aiY[-+_m&‘<|!;svn-~BV-`Zڕz>EO \vfg3e{O9M:iKpP7ʼ1$͒@ 8cr}.dӈ). Ѽz% vO続uKY!ϰ `.bM6A]`$#-hfXEg?7&tT.-|KMS2@4XFIi@ ,7JZG(I&-%a|8>=ao'9? "06Kͩ½,J؏s4e`= 7lM\y#dMdXyV;?#!y,R2gp? Ny(cbk]eUF| ""=INj>4UUd wYefqnڜ?\r&̣6Mu&j$L9i·yAVc5): < .͒tytxdž Ԧ{ֹ 8py]v!GRM|Bnj狊|7n 'J(XVw*QI'e-Sbdϵ_hZ?ŪH"ĬR/,\^  SFta_ߟxG꠭`b5TZ$r,0:-lR̪U^sW@"0Dlp(tz4Unmx2˷n]`RF@x[T]~!BM5՗{OY0'&Dh-8 a@b%FU7dhEu;[Ao;oѻ,tq"B`pVcW15* cÂnip;Jn}~J FӒ{ÂIT[J3>xsvDPsP4XLS>E:wo nUZS jaypRaC7Jg?B8uAc\M/IӆJ>ٸ(3Bלܦz77fNz 簓,>RWe'5#cw<{t,_@.NSY=N bc)S*_wJۘsbwO({T8܎E$0loQuB7ѥn>y)Y_UЄHWuNSAAD! 'Ճv&z&:Jm@`FiqYߔi%-qZ0?ݨP"a8x- _+äZӥTwUOZ%%rȺɝ` ޟĎ[z _&iHr1ǯ 4vaq%Eda*֍dN'_`ɚ!4-4맻;VObAOaj^Կ wՁI9{Β0(6Gx.j9"p H&ۼ_tEZqg:S:śv+] NYm)iZ0B$S(}ϴ1ێc~|賺^+"7*L8KENH~M>2װAE$1%,e]#'}ݏ7zo@[DgF}9GJc-@jM j]-IlԕCm?2g9ފ G2%F=U66ob6\bݰ&wto3G'Å N>Ӷx|I+C8j:vثtz,hl!ު03BSа ڴdš=ROp|S)];2,5fiK}ۯPN*8*#9o׽d"4~jw0\p@`*IKEޭyP;԰%U:6랗O: Xqr4 &YjM,tx1$v)<ߡT/t|k9?Os)nb!<BH"^FypsL 1CSaamǻZ*-64ԦtŷiL j;dVxz"@wZuVZb^tԙH& }_Dx2psm)-@~#3g=  Fx/"Gqp^|IH[ӆ4/,+xf -h6x22Nl4NS5@k շWU ΧV#]͢CNåNPP BOvmߴdIw[T@N #fHAZj~@ƯO#GbW6 .5H\k b<[Qŀ< h-[6 )DP߼U绵=}V3 YG{>j)n25w#eYvK^V=ܫWXŀLdf<Bzi#"(}tX-o0.B]'PbX$~=h ў%GNF^&CJ4 4Gt.ړ3r^UA+1|]Pw 3|Quzjۢftn` !=z$ƴ 4HFTI lR|4 ޙ8!zh"#de't޼}̵feYʋ=]z5%7ud|oc<,T><ԍw}oԬu]7ODw! :US䜘RsfQO%<'2JrEJ/[^kn&jpN4v$DtJ~],Hڹ79ZRg2x[9VtVq+ xBmKn)#*.j­c"v)ij!6?`T5q6smIQrAR/:\V/ٜ>P. dR+U~\h֗F܋pьП Ght0cw,#d=)T79W7@oOb'(Mn_ή`I#@}ex'n`cTvmnUy1rV5u궭Vfm6yg?9BICR XfK.IPHd!([Ȭ7N_}[3X csq׹ժB Dh1Ya2[oL,d救/ǪLKJ 3bʯ O,k4煷^g>ucPCRj"{nTSU!pT݅Jb:ޞc)W7oU 2@f#>KJ 1\37m@t }Ifohz;,YfoUA&sl ~/V)XT%kӊc1Sm IoswϏfv0S'! -Dk9!b(a'c}3 /ysEni^#.yƹ+6Y 3C>w-[n \'?H@C ->L[aLf}"豮0i ! d,F:ˋTyFN9L;"h}x?KHĥgP5op5I/%9~a(nt3SSDz BT>"Q lO{vnL~,1, ~{K)G3`m,M vž} ޫIbuPjSx^0 {[p<\%kZ#GpfJ_'k6o&ً>GC8>DV QS7;\1'Gˍqw %Qn,dJڱdZ -" H>iaAA5S0KܠS!GA1ڍ*ãjײ)yK _KwHz!m=%Li-ںW/ivrF`7[)[=8: `,MW̠Zo Utg|T#SQ\8o87{T?H N[qP/\q l]\la)"4yw ۷aAƿ6j h{>Pqid"ߚMFqܬ'vΔk䈓 xEOWNaGn>M:a Eqe%.Rw&$z,t;bw aicޚMZ o2y- JWh*ICi90Ֆ GMaE{40]3niJ d9Ĩd2TJ&fʿIJ.lPrmo1_{=w/ײ}tC}ho_ #J;F,$Ud[*/ZbJhȩvx6.+qԁ^ll]s\X詧@pl eI 奱"!v9{ 1|ݍ0qΧ n)0.8[0%9; & -l݋C]rNO {d&Y MF "ƧbDq'QY+q !Ћ}zt1ua}) D`Fz'P̏QYfQEnsFɕ^Nbq4j5 ؈s*;w/Gf !HE(;>mKdZt@y~D;!.uVR:'L*C{|YRXK2aO]lNrgd8V&q S^fx:UϬl(2iMMdH#I.k'R:sP"0QCϞf@;J SEA.-\ nګp)BKjA FA2sCT?Ofv;<17,$W#*g: Aџ0TsP k42992Y <p$$;c,Ѕ=̀LxnL'IiVCAsK%d)|*[m(igsu*m8QY-bE~xbAMh"Dxݞ 7`]l \< g;4e]w{=G6K SV:D[ݹ|Njfs錡Hő2/Vw/ !/ '7%h]&@@1Fyh+..4LƢ݅yL^c5v&Dkan^,w.Y%Їs D`$wSXeDߏMxz`z֝lzjvVк4Bp03?~Q ;kg=iV '1ASQUf7nY$tP,*ymN"][˞:$04vGv |8}ω:\\ ɌC ~|6MvjPp9ҟATƿ69s,ݟŹL~f5컡+nS8u٫ɪȷ]crEgB^#zθUّ`7KOv;f6s6Jp;O0*y}?uѣgY>`95qB1ڤ}k$o'JjZ`~ǹJkZBpIB1+ItGMWamXez 3g0 G:pD.K}_D][Z,=OE֛3؊Qظx|0 <}Hz/nmq|[h:unρ!8>MYBN X?3[?Q`VDͰ)>%@*@,yr~"6nq }c `XZ\ bVꀾնڣ 4bTv ,2f3'2ڏ^Sk2V*" v_v+M.1A-g'u~9++ &=fڠajEssHۥ6ۼ ps3Q}Qg]=9zqu[us󴭐d-/`| *σȃ,o|r1!; f7X'v{Ԣm㣚dǮH XpO=CAޠ`x؞H$qr:k&b ѻn(-x*Jg_ݫm;µ3,GseCY1$+lͮog-6,3.vK=+l0t={akZ 9$<.6[tKBc/{S_SٛF|s4_h-߾182zP%n '/gx1C6r BNS~e!$\/u!_5zs`џ{bC,R-7ww&I0&rN;"?sv5"O&@Də: /BEHu'*h~Vr.͘i:FBP_ ƪ>2 SKh Ө{({ 3𮢒Å!9 *%2 *$E: APힷ$a$>qu/U l~3Zo.=9E>%HW=FTCHR$EN! S`Gaxnܕe_e0+:}d[ұ#%nSfJs\v.,V4hUVd>R1UM ?M=Y:o]G(DfG$lhydp`0q pq=؇8m'޿<^K]$=s#x>E1coAVevD= P-c e 3 |Y(Z(FFx웫w  E)Qflmv̋BZ_#R0۰CjH-?CZߡ (HikV2e";Fse_@B$ rqI .q)Cuv`:aVY~ܔ\.swh.shkvasb"WJ o$)@B8GO-*#N/lB8"P!~kuu¦))\tL%3t,1P4V_g[IJI]bQcYN\ O岈u;B*]#_QDWm&C 4 _lLp0E"S+=*1r#Qd |/D~޿gQVJ;׈;Jo֨JX5M.XM"}T>gUj'7&ŸH|k'AB=y7S Kw9IK4p@0C(4<2yEnPt )5gtۯ@p5xOS>>i%nR/}e&vJ_xxZxA@CZJ_|,[,S]=MeJ8c baYȈg}2K6uyw ́M؋f = E \OkX;^|Ӏkt/lD#݋Z}wqZnT X5 t4߾xxV9?<}@ktgfSq^)xH%dgZT(2]˽a6N”}_ MmblXԥ(M1faygַIؗfHCuP67Ugu+{M mW PPn@^UzB!M(\ߗ`gxu8)x*8I-Mc0Toi*ZV1ꭧ6e.e#NdkWt:M?=&,!^tXq(O[Ux%-.US)95j^֐Kɴ fPXTZ\$fkPÈQgs4"ˆ=ˈv`r ~mww;U\a¾y&WÝ%`\Up,;Ij<ມLlwrm{Mċx}_NQX6RHtNFu:e)jU;TIf$7Be A߅x1G;1^bkɤ_j~,+;Um+oz^%hiCqNgvȶ!=k~}UFȋ!VVyy CrFqnA. H:k%\x5*BLDɡeN{K: )qn Fצ-R\w 'u_o|+}5(NYF= /jދ͖7դЕIXWބ%0IY%z[l'exxFJD#?/W@#尺}!*^ \Dptd&VWFvGҼ0Fgz9 SGL: 6ϪI^g2d|ZAӊHddf:&Gk<˺_z綀ow10,MEAucrZX!jN^p n :E9bBB &Ѥ'LT*-~-Ii.o(hg 5|@' B0^-moMijt&A!Up2ݒv8'~~t1YbcV5 EC9A}Fq.gqJ,(bQƆ\4)qEjxOSj\77~ݍ땅Fכde@dbӀRj ;aXDz%(Bȵl=0}6)c+1v_fvaH~vIP} LHCNWA DS$v^hqU2KbUyZnߢ]b 麜\')>%DȺd_(e;Qۅ/Mu׬*Zt"Ã{ ~@Z0E/NFpO9b6Ir{qfx 'T1e,Tb]l[oư:\\s՜E[SK#)xij*$.ѵz쌈€/!eбQ}ro87Dr.hvCRJkC^.u]/xS]2jN T-hBEiizF5PƙÑ+S7h́ o>iQE@sߒ}ea'b xupx& xFQg04]1/ XV] \$v7jd29͠`&J> &b v ^r'zhԴ EɅb 0H^{;E; Ehz^xx'`sm[6}/z/rYVHte[ö4#1ު)~|ֿ +G1n})XJ0c~ nwd:L7gB,SiM`GYsJhC/ׂ WoK?!GHa;R],^cZrn~<.wH#-GݶIӷL&bfStՇ'}wkj7Dhf('whCER~Yw*x-C)V4Χ鞽Mᗁy28g[!,R~(R`61INrpl$h:Vl#HGTmcdٸ0Muhw&bTG! ;jq=<0(&KM=E6ք+=3ϴ_z NJJA7;`g\{oZ ;:HF!n)}"W)ZH%\h%w~A%+˯EvJ^4vzfdA敫87b;|‹w5z֯4&P:4DݶF޶Di_6^@rS0~5bշ-ρ~+,nA;[>j:?;>[U ()AB8U/h\';+ _Џ@ 5 "iƒ޶9#/04m{ ko7{^1D)\h-M+7LȿU{O|zUR_^I_C>vCSݷ]ywс]@^PvWΰQ)ۀL#D^Pj1t:ANШ_q x8c%Dy3FKVM}I0r0O@|P%DЉ^0jWwd}喈m<đ Ɲzj4'FMk: xNn؂)+#Oz3Z32(߆Fqayb&>О=';` ؒ1O\[=?|6t5mHDDiu]?Hj{*ndޣڏ$U8P[5# 6>Ko fI$t]}~46 퓾]пŮ+AȗUDt#!'u^kGXrx _S)80ŅוP~nG߇IpXE`[!9>ZEXwÎ.>/8}K5f 2m( T˅5$ ,g+QQԻ=#wylFm4t7ffe*Cy;.+U;rԃwy߸\bEĦ.VtZ/+(k, Ԟ_ kƒy( OSxR|;x;@W]4@sK͡>b2*S@!]&`zT mWx{ї肟cNcHW ^@slSƾ&O₏vJybҾ C`9o+1NΈ͏x 8rO'+F]j1@M?ֵR[>{Կ'+j'xC#xm /FZUH:l%;P/@67sB躆!f0j/SJ#:]IAƆVno@#xL$tLgYB 8 Z/6Y sߌ;_W~ih1( ^ ^`2mXmtvXC,; (0-z-&؃5"Ag^?H@&+n'(2_殁ztG3f3"Q"cE%6s ^դY-Ƭ~r*+ B Z}q&r:r S>2~VߌcI#L2|J~@wKݦD]_te͢ZB"{#dvFͱwٌ,*"S3W ڗ* Zoj?Q{He "y1s7h~︤tTipL"C&&PZLx(ҥXW`c靰!/)iY&Rc?q@{0;EK %<"s@ĕx) m"iޓ}|ڜxQ}/ G(-7OBq %$Y'蟇b3!y?|,["Pwz?W0YǹFU05>{c4 dEC#+pD,_־0_nQ78# A+RxKĭĿ{yXA28h^. '1t0?4I1J`q<M;x< &=RsiVyʞTg9"Z YǑ-(3\Y8KzOi7vIS3`k!9jQ2|kП+ҧkE#m8.dE r9dC04W8D%MP )L EГ FgcDN)Sk:=yƷx2&=Ft=tK/<[bsx1t(q"A7g۪"+ڞvذNݚҎ|zfvF8OjXXoGL kdi8g꘢/M}reμɏ&gQX3HZje[ :d4o42}Qw?9ۤg]q%Pbk,!xěe$Z~dvOUmfVD3C ߽}-G&J~V -<7߂O)3-dZ ZX[D‹sϼjpciXͥ_EV^#F% ^}5jUcQ O[RѴ,c{Ҕu6ૂ?pUox~%ic DCp= }=I\ŸI.}߬-5OۧQޛ$ziwʕ^}aDSS"J-(wcQ"(2`l xUy蠿A 9!u ܗoZ5fPBici^%¦e3GR8"Qq˾*׳m6AFs|#hlCV ek/y';n mC!9\>'+f5Hle%h,m Z *D ەoF*W (l5Ukܑ/+\qKZTN^_3 DN3;%edPt`6nqg~cpcT^}G$+hHUZy, /ok38]*Ndxj!d;mb2[J@ISfϒ8oe6ե(S$]eФPK1ʃ:_]>}[$Ě\(ueo80Lggkv娜x-}/< 8%"})z>xOEV<1UH6q 9ui><@MPADo={B76:يOaJ8Ia) +a{Q|phY؏c-I,D \fj"iFT.ßb4mªJH_( C@'m00Y!PJy ;!1f2ĭgpha63#b:[^ &~olwپ.Ɂ-NYc[ɉq{_,M0ߵk cArĤ8l*Ҏ${0Yʪ8ꨄSomN2lgBʛ,ssn kㄟ Fbt 3V>R⧈s%Gǒ`a^*e> lpLkݶlT꠮=67 wC#9khM[M> 8ūUBR٫L30o}dP3Xsr[wI}4)9!,ޕOv|.Ҹ FH? EJ(`]YflsJ#~D(~LבЦmص6Ҷ-Z򫥐 r|#'5nl*zg;hx.UrH|3m`LZGu`^H .zLKpAPPtFs<Јǩp')R"cҮݲ=J ,NuG$hGpk2KP7 +:68@vZz9ĿCWG9͔Oh~Ada)0l &헸\ *i͵_8aF#BKR,_tDbyNĽnLcy}; uRcR( kCDVf%"ubّWvD2`z`!U&JW2 ;JX[2: ^wOnz~h_JH#[6߈ˈ/믆1]h5<*-ζ-P}kdW/c>PFXΑ+dZ9>9 QSȽjGȥEs;!MBrLLqPb$9~P$/0]d)l"JSV6v5@5ECX|h;Vc] |w6(`YӠ {ttl9YQ[V}d ]tU9oXnFqͿ<Gvg-8Wgjp\~>x]Fb2*ڄgםX(yҚ",9K=,~LgQD7(]Z?ۉc@C'H`Z?q2*acieEўw,)b3a E+~BFNbާpOd7NdxBXa hmA%):|1F"$C,Nt{ ̈́VjzN=m/V7)CG9 `ں)\Y1o蕍$]XY]#;NA,O-P_ftP+G3 A:{w <+bTls*_,I)*~Y}׊ա,e> hSH "ڄp 3rOC4'L5*NgFn@KJxwsP:daHGFp ["41@qXW3v2+GU( inG@_ >)# @"fx0&zB< B̷Qĥܷذr,( ]zeE*Xg&!D?n{w7T%Bn#Dm,(!ТVe7G)/og/t݇;}S̐o]o? M{뾅lyŗ>>NAj& uѬ,t3֮1| CICB=oA(+5~߁y] V4;Sp'"9.zİ4g{HR%x% !{/أݭ^c1Bp"Z]QM.N|%9`a&>NebăoMBl0H:k Y_uT.WWmf-|cR!pVV_̒*+cn1NLb%ŵFh>JN\oW!)փƛh332S#ԑo e:vڗ gЩz1kwU2=8w;K.W1:㨃l֪(Uy҉@*e[\(R9d^ߦ*ըB: rp3]b(.ĂʇcXUbdSVˉ5bIӍH+1%\J(R1=P&, ΁[`Q>lpoO˾E Ky=3 ZXL/ P fC=Vg'[{|s%N CGΈō,f3%[H~/*Hhc^sŏuӦr5Di ye\zv..vʍA\{FXiHZi r&CR ȍUXKF}{Ü"6Q(NUGi?RV9;{ Iή.N'V 9[.mY~Lh'`CN ~u^z]c MiTܙˣ 7BE$8(!"ץ]g%8l ?`,R Y B,} Z,~9Èb~vMݠ8 To3@o\3.n$5"zVig:{N6KOz;iŨl5u{9r!sP&l|j5s:qBzS\.x=W|ESAYƉH !tT~!9i*VOgmhnkjp'`9| 7s5r&G#u:#!ZDd#-(G^ A[[GS3q,7ݍ{Dٿy wy p5zn=̳;-z5i Юs{L@6-'pݖNz{*FN)?|4̖`)eVZ jp@$z$<>?t[h>QOK #ĔJ|\cYZc~C*>\5ꋙcSAf[h04&aPH5BR 7g||f8 'Ow),6+ɿv7@^oS-ĪH 0 tMwcRm[{mg}<_{RJsJ%Lf9ܭw4Fb#IJwN=ze$0풊їU CɔeE=)յꛠ$O+ xNg؅N@4~#J2%BҞ]c`l nivg^qS,UU! {[ͽtǘ,^1D/ch#d Tw.)n -Њ*k] HQ_I"_~._ 27yW!:ފ*[VҞA/WsC"fMrEoX _=bYBixe"uSP}ghS%Sr2PakEb84mL TmC\d⃒{Jl,e0Ԣe9.38 ܢ>OJuↁ= Ō6rFCvR!Rh1:M5Z~n̺&xx[bn;;(q< A(z߃+BS5QQY[ FP kwk-B-5,A# s0j&uR Ol#Uha!# ,3a G^e q.}z$U;V  ӎz=琉c93LCg'1ēGz+؊r852zR007M̟q j 9^Z{ar`A˻x߀,_35;7/B uWl:Sx6yr-1gul @6"K`Q Y?&vl*j}ejByc TS9~]vvu=I2pX:HMcWK(p@_`+g nxaW/ -i92. gl %@̺ಸKa@R ^^T E.c~ԁ0JXPNaK,y}}|?^ "8`mWv0>3͡0{~ DqA7دE@^hLpBBt~DPRaKo9B&> LgfcCRxӘJ7fY95sHur1P5DW}ͻR­ +b(eX%˽nB?IZGoSBy~@h8.m儐y)"]ll(]6/G+$ U_EHc8-Rg 7g @&:(pJÀ|.  GY'm 9 *϶4\ċ8~UlöB^/+a%mM$,.VmNPzjbmsӷ@^Բ'| #JӴX C[;/}L۰Tq<%<,$գ8 uiZSI#\8L@[ q ~{ db" I;NCG %t=G7SB̏M .̋}Zzڞڇο@v5IL+MraSꥂ):b?{WB] 8+Whn%Fy~rP[8oVV0AYͬvhJ}.zr%ԀRsḺR5sބYPtrxBNc:RԿ"8?ǮH$܃VpY;lCK.ﯛazCAzAcY@BY[~9Jm$SugIu7Od9oTP3xy?#yQ"싨Mn6'M̾/pn DQt 3[,&ھfMFeXoijrقRr%w,j74;m}-A*_ $EׂPqratƕMCn -~C yp WjG3AAvIxr$#LEI W+p֨D|鈰 F(7g0 RpN2LL3ǔ^e9KjтfB  eHmKCzibﴵ@z}IJ0ᾖD}T@m(T],_Ǭ? rG ?Fk;![[iU" =_M3K:B.d,T`l4d-0ۦMN@56L,lfPn7&4T21潗t7QEy4_Wg5o5@+nQ`?;(LKՔ2dsO^9 {275}Lv*zv*9?*bI֜~r^jO|c%#c;g25FڛEAYAS;FyJ\ X! M:#cn:S)A'0i *|K;+ 9[+ 3H|.Σ*fCcbmő)#k!*(BFl7īDEpK}_D[ZO?KǺ넝!FP3.VANcr,7 9Dэ4>ϡs5EL{W >tYF! wz^t}Qs&crDPKqT}v:0WR57f{@~OR_ ;$Go6^Zn=~nr+ι j^1qXqKs/r0>)! fRIh]WlA7KD_,R ËH3jU #tc(9Xg#>DLKnQ YloxXI<܀_5WQT`z@%Kڀ!o'q)UZm(=yU8STy9X-툷7rI;:n`7Iw\El̷(H3͇]Y짚讆E4l~_  cow^۔帘Ɓ qYc~b \r66t:=v7\ w$#zdY3u mvӟ4ę&g, 0= ,P#SMFD*DN6D]ґ#3MRV5lw, h`"N}skǨ*?Wf*#4+SWԎ5^MRI\1<aNF>Jރ3W\&|M64QOꎧB:r ;#+h2&s]LL<Wu!^oy:I4ݔNJO?U?^Y+@L.8@~*p=6Qٞ6g6mZR3u6$JfOjF]- $N#eO\{? ?qzwJzG`#uznnF3PM410ɸUSۜ \z*-#mO萣'y7jtzCg/W סf4.lR9QX,7 ;Ti LKRyw0;nGXcAn Y&m Џ)e~Ej"-ʟ1V:hhŝ̓qX0yDO:OƄӋo F]B.['H[ >fpb^dXB}Qާ` wq<33ӠՄe nqye.}\lH|n_dVXos[g;v\5K U٠ZҎ}XƂȌk<ܿcr/fFGL&RZ Kϻu×@rn5ADiK cB(yɒ- V76=+m])(^OȚGW6 3^)#?0m|?g^3 Ԣ%"b&a4S%BQ$=2mSȘ籢̢i112GI$iImT_杜O5Аc=Ғd5CJLޣ-8(2Py>,ݚ6p2H{]SöI JUGfQ&`Zʁ0Ev徚3\Ln'> 7#VNzʻ!IS8RO"Lɐ$zZԂpm[4!AFęBٷk~Ïc5ZZ+f&_|r#=_bR PU}FC(Lk"oaJ`v;/s~2{"Nh=ɁYXq{ö]of֜i% 2DNPo 4  $[fO[ ̠_ԖRhSyr6sSwͭ#CX=sd1$bW2XT5VG$%vyb!6{P<~0B+L^8~ gXf.8;QWI$>(|d,#t@h[:ԍ /9EE.˼dq}t$Et.M,kp؁!?&j)gz֩˹ٔЛ%DM[^|\ T3|<4PTY) J 57Sg?辍nQW<DNT YE\y[qf3"o\RqqB g_Bр rSQN*siP?4Av~:YX?8R9ȭaY$HbzRgK[efپY)u#C *cQ=J$f7?SGlC`z'Pd>.\\D^;WTZa /DFkgFU%:mX-2Tďs DC;< \ܘXayB1N@`4TW`dlN2c34gsgf2}QqꩾuX0hN !ohM0:MtQH:f6E=ZljrNnshֹD[KghrL 9hQ QNT``&P9Ś#ZLר/븖 ˛l&'po*3=Fu2J W6OXUXO?"6iխʮlu ؉)eN& 'BK)[d`'9|4(&~!U`2);1݊uFO>; ByG6cmoPUFJWb&+c ٱ`R[R׮6J)SG<=^ Kv TNMZ&m.$ānEqFZ#4YrJ $?AȐd lͺk5?&"PKؿ؏gAVr3ruO x0Bx{FV0Pʩ|׺7Lu0"b̟ڐW~W^LIz/4~NFVGXWℸfJ6`JG`:%^W1i8`*yZwEhK#ﱍذ}].2U"6f@>R&>aXL%W!C H-+R\GW,Eh`yX!Blq+ x2O9f"N%S"D\FOYUzw>ЉZ)NnѨbR] !'?͢ى`1j܋V Y,}Z /ҵeaZk:sũ)ͣ &$glˋuH, $g%B%IB?Rȡ#6~҂ ρ70e[1I}/&RB@{wӼ/yM!%h z@GŞeb1ϧ!m*#ԄF?䩘M4<^ i@>GW*J hfH@mgbНa&|pF3!AY4b6}df95xǠ[x2z.ٲnl+PxnM \}i|ub)jnl#ia5Z"ɫ _4ԑ r C,կ PK#,;.-!p s1):uPe;XbĖf/$Hra)SUݐ;Ȁ2t.] r[^GBsȐ5tF(OAtvVZj{D>ܺ6zHλfbo-$> aH2sar`V7IFR|>HusD <$bX$\w 5n5<ΆweÎ tjMw#g+p#1)^P6^Xp`a;@VxP]Bf ,U9NZ7QQHEE\bX+ׇ 2!{%m.b4RLVYeCpj̘ǯHJm ܇JZJ}.,8Ql DƦeX@t]Dn03,Ev{F#t0]tHc#>D 1hQû-qHѓW s*6(;!fl5[3MAӾQóSFI.g^>aPynM9!^*N BYuv۸@Jcj(zf&-zKߥM㈼UmVQ/+ICoZg=?"91wQ9c Or:'&l J}Ɯ$[P) G.GЁ &,1jexUH0n' 'hBb*Th5Y.#ݫu>@E(GeԟRR;/OzA1ƣtkoe EO~ [蓁5rfG;ųz8lWPjjGs:>fV]O$V>*K; 3t3؃ѣO'dQvc4`0ԅYQ^HVc>k֐B}F/ X\l^(BE6hD+`nCt9[:G6ho:oDrWpn{2pرz/&syWO/H9cQk]qGʇ%Q <j$o{Bg=2)?ɌUơxbQ|> J{̾/.T>@P1IRsj=_YyeO]'1^ ,ƒmLnOVŁ+M#խ9Ʀ~j Nb*DZMx?7Z3JDF(e!Zcf&=_ 5Rʒ#Cc}KQ3/a']\.]ҏJ9'Y+5 E"%H/5!ea"ZFEk_, Oev2oENF]dTlY(gQzy#OP5WQ9~6?U/2K71?'bCOT7M@  $<vLx;̇ki (>`3bWJK[Eim-iDVAXC* +$s9KP.7)~9,l'Ֆ :0zޝtM1$D + T_َ-(M\R}vO77Dȥ)@BaT"h4K0ozٖJZ>*\C68tDLX kCF_eJdܰCہ诟6`6 &; j _!LbhՅB_jE.Q[f+WR 1M&xGHXdT{dfٖo%'HfCp:! QHvv~!HA-vjicpV-~Qt6CK6=tgtʤ}UP93JȕHß_9 J}C`ȶC[h ݽ r<}U kM_`^2"څ6PW\abSZ+35*,{ ^q{P}_rkѢ>6R2&y e|]A{brU*tw3ywi$*)$hFAѷ&u' *Rj\N+ 5j VE Q6+ݤ /Q3 0C#duwИfr>EZ 6a+q?[րY3DLm^Nx"m lwq*Itm:ef<aϧz> >,ધ{td_>vƗҟlf[`d18ٞhDz(~+!b:UylL D#ɼ}B!79iUJ 4Q#1NQ%!'4ﲌ|ΐ,JTļqDXuKFZB12j5h M+ݓI#Ͱ// A3l'iw懞Bkgsw>dheՒuy/(lO H)?=mjk^ M#G` t '}(0:;m"GU LQkoJ D1.H`5` ŝD'y{ޕ5m4T4\ߚ0Q,;G˗nb y'LaIƄGgУuZb;]g_HPMHMlF |bePf h{9e;dR.9ij+$>ZωRX ^C τ^]#byͻPnK}]/$ɨ. sO [6])n5elEYZA3, ~HZi&J˨ *1 k3vaUyz EoР,koVP5=38c*[bp5۟ků".eMʹńYJ>K=Fɺa:ԥeWnYu8$ǕޙֿV1R=jҥ&7l[TzX)j ֙Dd\V]VCA]̳VoV ́rAqDQ*.wajE'r~ǁ3wջ \E ? ;GtaBEcˣ [(UO5|ٯ^טA_8Rr7äR<;*0&<#GFӐDܣN|F:ѭ4zO砖OgzKl\}WFwK>A,f4!;?4)Č\&Q5^Rx?E(7YڏnSg]so'i32C*3Ė ;:4ug 0xqd8PU> @7:>-N2SSӱp g3cg fk)wo1Z@5o/ܨRA~}O+Y4I0M)]HZT\JW\MN "ml- t-V.'T 3Yȫ-M*07o/S ~#S^T C-ٝe0;lgκjF `KW6sxMRu[]͹`5w{ FH7`+?Pֺiz|ͽx<'"oY$}[]8ҺYc4)jg?\w~t]XX [ m^gb7.צ^YKWr(q6 J?gW+e.$]-*0Wk霳*,GRuX-I*?$Nr*lLPsOqG\`U%rC#C~8jl$Z%~p!ۮȂ{SQ'A$2+sA $Oe)W*޲>,!M => x{0sE Voƍ@i&6T| 34f:hJ -mՇNlYcĎQӀ7Dis;$a)V%ԙQܯ7TU]1lPPv?Łpa@=K9gcU*?¬e8{= CTWűqnvqat j~Q;w=ϮZ{\=@5Ǖp:^!UL =ZTXJ˺9|a9& ~F@ 1v̬_fAp4>ԓJTcST2I୊}X0{?wQ_n#߬%F:2DžtP/Z ~-j383IfZ$ ]ji3Z1A`e]nzy ǧ޿; B*ZsaŪNXM86)\mN(ZaͲ/iQ7"5#c3sJj 0-/3_M>9Fy@\wi>`hN:(q(I4} KԢ<^?د9PyRқ 3[[!'~ۼSL0iK8rA^b'l/"j'8hsV ET7qqWLv5Odk&RȋlOU$kJݣ[heC6l{Tf;w&z-P]Di]2KM@R~E n^K}+Lm4WT@Uv*dn2P9),g9kq3b'mT;DNsMsu dڜG|^O*Rpx1ޅRhM9 |AKb2pp8}࠵ΛnL 3/qK Iw}Jp2la@flጒp]JyJCi]MYLѢ$?36\?93j"5FAhu+c

7nG.}ĕ0,x/]x c Z@O;C6R?p%&T*⼯L %zwVc$]˅RXOcͬKn4awkVm~<GK6_Lx+&ZaT$q7i&z\/e *8Ma|9Lx'9KFR75kGs廢o-{5"&av4&n?H(aOl<576{woڍ]竟UYXy!YB  QxL'afi >wNCT|nx "A2$$|+\f۠[4V%e'Hp?!()vhиq^YT#bK=Ls G2x~ͲʜwG0܍0|I̠u|4&Kkm)[2kz߁ymT+ x.UT v܁A^]x/ 4Zfa_-ZdgTT}"87w%Ks#kk1yr+5Hu GE%EVCfnWJ>]PA>D.=>R<2gcv!lt;zy-];waXhg/W2:╝ >Lx3U`w'穤}4A]#jû]5q ʂc5?;](XTց"'=,)'7;=Dž֛ϫRۄp" n&ɎkZ)u@SimP0maY]ݣ*s= `,²`J9Vh%uYY i&*3$pI 3 )\b;PP7c֘g̴9L u}3Q2 .Jf#)h}',ڰ}&=pmV*Z!'(ٙf!b^%;v|TGn"79yF왲y\kE'y1(%T`y Qx=- +7V:iL%9+̤͡iSwµ |-:ur.Hf&Q#!,7 (ȥHصLߨЀYCxUi Gzdg29ZEge(@65أ7|py%ߏbZϜJ|g*Wblɴ3Yn:eB[NP]~cou%k55ꟽ੒3i&inY}E@ ܵ#ÒE\ЕIx0.[$s 'z&/;qlrGiCL$h]BfL+C9'KRmށG81.TK.i \qJ69b/i9j%raˤh(2f!:rX}:OKt`dk+_Ih|c)).܂z۳%pق@Pu@; "wݮ4SE@Ǹ^J܈TKcr]P8>r*jD,jdx&S{-7?qp@㧞 !ǐK3yk,?;`_oW sGEc>=AЮHB E.b[\KӡLv_mDz~lo!"p^0A-8pWI֡U&c+I1~o4P1 ,eK{ڲtkĨ7>Rz6r(8ٳGGPcOt*e͜3FDU@ c ҰZAi s Fx\Ёr3eC('118otIzT7dVTѡ 0!TĥP $\k3Zd;\^ Dburc{G[($eNĠSrgqb%tNz|P gdTFdC+(Lhq}@а]u*ZKgdڡ QJx[R jxa]wR":/7G$&mbbP_3W=جŘmM{+'? A0T]‰o? ̇sl&#yEĄpωRW\,> '2n\9^ДFc/':lx)Ń*UdFqF%syrۼv"v _رd 0'+' _ӡlՂ8ڢzJWŮQq'Αc}Pt,ҡ;O=~߇zW{öGwxcZۛ pN!C~olmq h du!yy1q 5 nžLln;Oc)JT쩹=$cUK+'SPc5}W2/1#jQ] e} y]( '?p ~SǫmXw,FC >?"Z# FhR#aRWw,;IBe}.!nX`鴰e>]:W;ILuۗe)M;Sӗ_;_W!>(ɯ XC AmKXcj_@9Rq;w"1g}ⳛ6* (<Ec:a3U֭1Fa:Gʦ'n~zs]1k1TF}xfÀEiM6N³Î1?B[L6)CDk6.7@QjqZ$E$p8>$ux8P;CKg: &#"mI:ѥ }L횢v*#T8ZN F\;AX;r`ڋSԱ@gMrU%+Cs־jL0iu8"B;xi"Lpr c-lך*m?~4&n1 1 }, ?*E? _-0r$IP3]skDzx4mq)AniřcflL2=K>FpZȒ]l!G#|zEPG|jiA 1yqx:Q|2|V6t$8{ݒ#ĵ4e=|IY@}NiA9͍7B̠cd @wit1v93k1ˉ* 3ӓG@  p dpsczÚ[//,-Y)k}UCC(gn+4ycU % W,/d?غvDggִ\u8!> d`*po@$31lފ:D EJ 2stD`2>b̺ňMH7IsHƀaE'v͊(B~ xSŧFIXк̒h >Ң#T\Hu0@ Z!FBZ SFgld3w"/ּk1JtN˫Rt) v uN׍]JY喛?`NON^ULB(yHG!LVZ)kFQL@g#"M[=YEMa-lplo3y~0vIx#RZMu32Z ɩuyci3\yRH5Փ'mlUSq%1ׇ>U\$Tw Y'=UqUQ*K1`NN qŇ~@?2)lݛ_@l1iVҔ x./Dϑ{s Uώ=N#G{E#J5#԰iϷ| $F0c10mfז I6 k Sp?yUV]/k-Cلb[!-ٞ9/<_l3ҽ*Kd0Uں|0c~{>YgU{W9u%DV3tqi78cVb%zu!9%VS$pbE6 ͜I\:} tt 2Izo ŀZot܇TʾXs\@k*Ө ߙlN# q4(/˦u)9_i%,sahc^Wid #mh8MF rRK<51g wg:"!*c3[hĦsFVv3MR_.'dRm9"{w׍XvIq6w'貳B*CvgNz_cԊP@T&-5ԠbDy oqa['W RF%#[2u(A% Wo$;$ܖ$T'͙ϥxCC Ȁm,HepKdQ{:/?N=ܗbJ=( +9{(x>4:~6 Jd8=#^,Uƶ~:?Ӟt"™TkJO0[ t8F^}!A*kc'\6 v;wI%\hqECWpc|Db{q:9H![aXT-(HDW{\*{`\r"7֍c bhISh3PAiBq5 +:}ᩕ7Gy"eM2!p}&%5T~dOAt+溽Jh<HTxqՒ|PNMcmP5VZ+QrIšA?1d R6*آCy}׫?ZwJ閃.Eun3CYiCiր&H^y I}tv 0畀Ll߈lInd(,1fǑ~deH=g ԶH?`X-=fa;0TddkBGZCŏr'>v45PBK¦NRQ%Qn-}[ΔZ^h#> N( iQfMWٟp4/)Yt^֕aTs6q[`!RSt90GdKui8ri N`/QljzF8BV7GvL%7KRyC L' WL MyRZH=T0J;{{?r(0~_CjFF/[&*&ˮOĊG΃ρrB xZfI6]! YFa:^Q:Rzҽ%(=/=KB i6xk;";v^&.]QKxrB*YF{ 꽽& K'>y%8b <lG ǒuZ.ode{9TQlL15sk[j[L)~,|D% a5@3LEJ !Բ`ه\/ M!r]Ws҉9Av\PLy&gtqZ %eo҉D,YD^(i.zحB # o^H_'v> `4prb Jv5yaa ct 1@JB.2o-3Q1f}{.Y9 =%DZܖ-1GtF4}Xh%I^Cmө^M3uX}ˀCϙJknK[)Y$TTH~ik0uML-D}14VxfV҄X_^GK1B02ֳ}36 QE+¬Bff#&dϽ+ۙ_7!q#|:'nS꼲#tQWBGL a@!Z|Y7tY74[=Iu׍ꍙ4o@~Gc!(fx26$uJ/"KJ`ŸZݣq?+ FK%K]>?FQ"W>D&|E􀶦Pq!Puma5q5H:E5`8%pW;eRh[{oDrt<1]8L)؀Iw6%68hrҬM(JS8:f!o Enє!J:Ms5 ,qrE{g U-|SjnKE?8P)2J/ 2Qjv#ӃL*Y9uo!QB[ f(O't @ɅWVx8xy={$^f#߄^F>:o8/ jmaFBt;"j#5ұ{ې9:s34$_¬ֲ=imޓƭԴv"@ y)14*ė4D:Lqp[Zx' OMh^Tm'DdBJk'~apP^[bŕA*<{ rAJ-xts7ẎrW0V&ҧV58#K'Θ2z R)8A2=(doAzQhZoWX[ #O“ Z&H8NA`aJxǕrWw^m~ nh{D3{d;:K<;7WxaJڅ`2~LhE40SI)d<gEn/4)ow JRѶ9^> *l"p1vweHI)kQ)0#o!a};G_I%=F`q%'ݲ%))fLhrc`9;Re\#*}f lې˟#3۪",EL@Ewa}ghrUh^✑X[HPi5Zh+;ui틤+ chڪy~M&h(d |D_RGuԘ%E6]vSRB[_srVpf⳪g$_wzA|yVs|kS_QV4cK|[{S 5-ˠ3qD|cOFܲTWYl0}XIew>~hM3X79y\ĝl.;`#8ii?zlFjXCC8MJaɥoףIF AaNZ~Ec;p"bÁ2M{[8Mupmt[PA"[QU?PhSyFDͧw~^`-DT~ƭn2@Lg<gLW9,!KC*5f*!ϙAFU1,n+_%&\; `Ox_ qaE ;D;87͙*Hg$3䒝Y PNp+eLET6N/i`y+E |FOM HE*\J6ƮSs42U"Ƈ+0ZuŊ?ҘkZOӣJ,ZM,{Swȴd(x!bpXx*9AK+G9KFgՄd2D>1Ah؟Q@ Ed2!&A9;c`W»9 B5u23U)<}B2/aZv"^8GG#2%w rC?|;eP pǼB:g%'gm\Ӳ]K_./&d@9֯1_-R%Wp r8Wfv0ߋ5II$J5l un 5"=GITGx+erb0Đg_Oh DPʘ/]* ¿1't3x.Uan>=`RF , n4ar1 \ # g8;= wWGnOhYZZgڳϙ{m~VQkUJds:5iDu9S`ce3Qr.!k:ܥEXJH"%i`C* ;ԋ jes*aXUal_Qu o*½p.]O\e{A}MۣU G.,rKݠbn@ڠ!s BA GPih32Lzyz}~}||}}~p}||¸}ij}½ʺ~ǽɻiɶU´ȿL ĶúߛLkƷA^ %zλ &n##Ŷ/"3ʺo! ?<+U2!M+;ג&'ʼ+Ľ,Ľؒ'!&ʼM,!;?=+V2"o" /$3˺o$&ƶ B_ %{λúMlƷȿL ķU´jɶ~ƽɻ}½ʺ}ijv|¸|}h}||}}~{z&{|}zyz}~}||}}~p}||¸}ij}½ʺ~ǽɻݩCbɶ4z´oȿ4Ķú{n+ M{Ʒb*A *z[rλk& nJ# Ŷ"#ʺ簿Q!pr$#5#!n._ ;ղb ʼwĽxĽճb !ʼ.` !;s%$6#"oQ"o$$˺K& ƶk) nb*B {[rλú|o+ N}Ʒȿ4ķ5z´ުDcɶ~ƽɻ}½ʺ}ij|I¸|}h}||}}~{z&{|}  \r MKC(/do" = \6M[`=$ 4Iq5 ,-4 l' 7m*7 v—ĢIBlGT;Kfn(8 y/#;/5ޯ?J߲Q<# ۵T4Q ܶU4Q߲Q<#߯@J y/$;/5lGT;Lgn(8 vØĢIBm*7 l' 75 ,.4M\`>%5Iq¡\6o# =D(/d NK \r   il32 |z{|}~}»~̽~μƵq }¶e _׺u@Slĺ34ηF иmffտ- WyһE,ҿE,ҿ. XyһngfվF и3+4ηu@TmĻf _׺ }¶Ƶ~μ~̽}»~9|z{|}|z{|}~}»~̽~μiƵpea¶ҡLG׺V-  AQĺ$'η2gиrNH Uտ2iһ|,'ҿ}-'ҿ3iһsOI Uվ3gи%+'ηV.  BRĻӢLG׺eb¶jƵ~μ~̽}»~9|z{|}  cp2m32rzOR,)| L}5 3#&G5-ْJ E }6 }6ڒJ E 3#&G5-}6 L,)| r{PR32q3n c is32h}~ؽïߚM¥I$ײy Jֵ a۸ a۸ycJֵI$ײߚM¥ïؽ}~h}~ֽݼïԊ=¥: ղ褮k @ѵ [ٸ [ٸ襮kc@ѵ: ԲԊ=¥ݼïֽ}~ yS!Yem8)ۀݼQ DݼR Dem8*ۀ Y S! yich8 TTTTTT~TTTTTTTTTTTTTTTTT*TTTTTTTT*TTTTTTTTTTTTT~~~T~T~~~TTTTTTT~TTTTTTTTTTTTTTTTTT~T~TT~TTTTTT~TT~T~T~TTTTTTT~TTTTTTT*TTTTTTTTTT~TT~TT~TTTTTTTTT~TT~TT~TTTTTTTTTTTTTTTTTTTTTTTTTT~TTTTTTTTTTTTT~TTTTT~TTTTT*TTTTTTTT***T*TT*TTTTTTTTTT*TTTT~TTTTTT~TT~T~TTTTTTTTT*TTT**T**T**TTTTTTTTT*TTTT~T~TTTTTTT~TTTTTTTTTTT*TT***T**T*TTT*TTTTT*TTTTT~TTTT*TTTTTTTTTTT*T*TT***T****T*TTTTTTTTTTTT~TTTT*TTTTTTTTTTT**T*T*********TT*T*TTTT~TT~TTTTT*TTTTTTTTTTT**T*T*** ****T*TTTTTTTTT~TT~TTTTTTTTT*T*T********.3***T**TTTTTT~TTT~TTTTTT*TTTTT*T*TT*****4^ *****TTTTTTTT~TT~TTTTT*T*T***T***** X***T*TTTTTTTT~TTTTTTT***TT******* ^****TTTTTTTTTTTTTTT**T*******4--^^XX **TTTTTT*TTTTTTT*TT*T*******^^^****T*TTT*TTTTT*T*T***** ^^***T*TTTTTTTTTTT*****-^***TTTTTTTT**T******4W**TTTT*TTTT*T*T*** 4-4-^*****TTTTTT******^4.^**TTTTTTT*TT***4_]****TTTTTT*** .^-***TT*TT*TT* :W*****T**T**  ^X***T*T*TTT*** .^,**N*TTTTTT*T****4_X**0TTTT*TTTT*****^4 ^**N*TTTTTTT*******3- 4 '^$**0T0N0TTTT*TTT****4X**N*TTTTTTT*TTT**N***-X***TTTTT*TTTTTTN0T**** ^^*****TTTTTTTTT0T0TN0******^^^**T*TTT*TTTTTNTTT*T**T*******4--^^߂^X ***T*TTT*TTT~TTTTTT**TT*******X**0TTTTTTT~TTTTTTTT*T*TTT*T****-^***N*TTTTTTTT~T~TTTT*TTTT**T*0N****.^ ****TTTT0TTTT~TT~TTTTNTTTT0NTT0T******-.**N0**TTTTTTTT~TTTTTT0TTTTTTTTT***T*T*** ***0N*TTTTTxZTT~TTTT*NTTTTT*TTTTT**T*T*******N0TN0NTTTTxTT~TTTT*TTTTZTTTTTT*TNTT**T******0N0TTTT0TTTT~TT~~TTTTTTTxTxTTTTT*TTTTT*T0******N*TTNTTTT0TTTTTT~TTTTTTTZxZTZTTTTTTTTT*TTN*T*T0T*TTT0TTTTTN*TTTTTTTTT~TTTZxT~TTN0TTTTTTT0T*TT*TTT0TTTTTTTTTTTTTTTTTT~TTT~TxZTTTTTTTTTTTTTNTTT*TTT*TTTTT~TTTTTTTTTTT~T~~T~T~T~TTNTZTTTTTTTT*TTTTTTTTT~TT~TTTTTTTTTT~T~T~T~T~TTTTTTxZxTTTT0TTTTTTTTTTTT~TxTZxZTTTTTTT~TTTTTTTTTTTTTTTTT*TTTTTTTT*TTTTZTTTTTicl8TTTTTTTTTTTTTTTT*TTTTTTTTTTTTT*T~T~~~~TTTTTTTTTTTTTTTTTTT~TTTTTTTT~TTTTTTTTTTTTTTT*TTTTTT~TTTTTTTTTT~T~TTTTTTTT**T*T*TTTTTT*TTT~TTTTTTTTTT*TT*T******T*TTTTTTTTTTTTTTTTTTTT*TT*****TTT*TTTTT~TTT*TTTTTT****** ****TTTTTTT~TTTTTTT*TT****-^-****TTTTTTT~TTTT*T******^**TTTTTTTTTTTT**T**** -33,*TTTTTTTTT*T*****ꈂ-****T*TTTTT****X,**TTTTT**T***^*NTT*TTT****^X4***TTT*T**4*0TTTT**^,***T**T* ^,**N0NTT***3**TTTTT*****^44**0TNTTT*T***& *N*TTTTTTT****W**TTT*TTTTTT*****,***0TTTTTTT**T****-4W*TTTNT~TTTTT*TT*0***^*N*TTTTTTTTTTTTT*TNT****-^-***TTTTTT~TTT*TTT0T*T***** **T*TTTTTTTTTTTTTTTTT*TTT*****TTT*TTTTT~TTTTTTTTTT0NT0N0*****T*TTTTTTTTTTTTTT~TxTTTTTTT*NT*TNTTTTTT*TTTTTZxTZxZTTTTTTTT0TT0TTTTTTTTTTTTTT~T~T~TTTTTTTTTTTTTTTTTT~T~TTTTTTTTTTTTTTTTTTT*NTTTTTTTTTTTTics8*TTTTTTTTTTTTTT*TT~TTTTT*T*TTTTTTTTTTTT****TTTTTTTTTTT*+-**TTTTTT***,W,*TTTTT**W**TT**3-+0TT*XN***X0NT0**3-*TTTN0*,]TTTTT*T**+X,*0TTTTTTN0**,*0TTTTTTTTNT***NTTTTTTTTTTT0NTTTTTTNTZTTTTTT*TTTTT*icl4̿llll l ̼ ˫ ll ̻ ` l̯_ ۽ llll   ll  l lllllllͿics4lͬ \ ͼ lich#HnmYUYEKJUQR*JԨDRJ))JD PDT J %ZUD)UF DQH*(* B @ (U#Qw$HA R*$ IQ!J@U)R (J )@'*UPi$ LADI*@UT@ JQR!U(@AJT RJRIUU@RTIҒH??ICN#?mHJ""T@RHTD"Y}ʀP?@TJT T %!Q JU$I$HTJIJ5HY&Eics#HZ$J@GTU JRRh8mk um tjqf qf l8mkJEHݾBs8mkޠޢޟfractalnow-0.8.2/gui/icons/icon.ico000664 001750 001750 00000261736 13175112471 017151 0ustar00mpegmpeg000000 000000  (~00 Nh ^!00 %&)  N hv_( @xwwwxx|xwwxȈxxwxxxxxȈxxȈȌxxxwxxxxȈxxsȌ18ws70011P30xȈ0ψqxȈsxxxx8xȇwwxwxxxxxwwxxxwxwxxȇxȌwx( xxxȈx8xXqxqxwx0xxxxwx(0`        &#$&+,+++.#2$3#<$=$?*A+L.M4L"4U$6VA^MkNl(Ci(Dj*Jn(Qo-[z}}_`/b/c$n'k5n5b6n7n8o8p#b,z4{5}={>|/r4r=z4w4x76;JBIQI=;<;MKLCD@GTmMK/T[\`\QT\`fdoqlnlrvy/-P?pRcv1Qqϑܱ/Pp!&,>X1qQqwvsqqqqrrrrtuxvvttttuuwy}yvvuuuuv{zwussssssvutqo,,,,,,,oprwvtrqqqrrsuywtstursuytrppoprqpptxwwqpoo,oooopquwztrqrststvzyutvwttwxtrqqpqttqrv{vsvtrpoqrpoppqrtxwtssuwutvyywvxwuvzwsrrrqqtutvuusprvtrpstqpppqrsxyustuyvvw{~yx{xxyzvttvsrrtxzwrtropsvurttqqqqqrsuyxuuuxywxz{{}{z~{wuxvsstw{|wsur,pqtxvwsrqrrrssuy{wvvx|{y{~~zxxyuttvyzvtuxr,pqsx~xtsrrtvttuw{zzxx|~|}{}yvvwzxvtrqurostuxz{xtsstywuux{|yz{ɞ|yxzzzvssqqsrorsssw{xutttwyvvx{~{~}ۤclʪ}|z|wutrrqtropqrruvyyvuuvzzxxz|~~њYZĨ~~~{wuuusqtrppqqrsux|xwwwz~z{||ЂT(0fĪ|zxwxwtrusppqrrstvy{{yxz~}|~Եg# Aĩ||zwusrvuqqqtuttvy~z{|}̮`!EԺ|yvutuyxrrrtxwvvy{}|ڈP^d>1 &1 %;Ihæ}yywyx|uqqqtuttvy~z{{}̯`!EԺ|yvuttysppqqrstvy|{yxz~}|~Եg# AĨ||zwttrvsopqqrsty|xwwwz~z{|}ЂS'0fĪ|yxwxwtquropqqsuvyyvuuvzzxxz|~~њYZĨ}~~{wuuusqtrorsstv{yutttwywvx{~{~}פclƪ}|{~|wussqqtrostuw{zxtsstywuux{{yz{˞}yxzzzvtrrqsr,pqsx~xtsrrtvttuv{zzxx|~|}z}yvvwzxvtrqtr,pqtxvwsrqrrsrtuy{wvvx}{y|~}~zxxyutuuyzvtuxroqrwtrutqqqqqrsuyyutuxywxz{{}{z~{wvxvsstw{|wsusprvtqqrtppppqrsxyustuywvw{~zx{xxyzvtuvsrstx{wrtvsvtrpoqrpoppqrtxwtrsvwttvyywvxwuvzwsrrqqqtutvuuxwwqpo,ooooooquwztrrrststvzyutwvttwxtrqpqqtsqsu{utqo,,,,,,ooprwvtqqqqrrsuyvtstursuxtrppoprqpptwvrqqqqqrrrsvxuvtttttuwy}yvvuuuuv{zwtsrssssvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwvwv( @      -',$3'4-@,E2F2W3XASBTG_Le&Hf#Nm-Uf)Ql,Vu2a}5gEiy~~3e2i3j3r3s6|6}5LGORQJrmn|pz}c}ϩ1Qq/P"p0>M[iy1Qqұ/Pp  >1\Qzq/Pp!+6@IZ1pQq/ P6pLbx1Qq,/KPip1Qq/-P?pRcv1Qqϑܱ/Pp!&,>X1qQq?:877889;><;:;;=A?<<;<@>;99:9>@<7555569>;8799:?=:<::>9777979A;::6686568;>:9<<;>@=><>>9978:<<;87::9:7678:>=:<>=@DAB@B>;=99=A<;858=>:8899:=@==AAB[a^[D?@<;<@<:<87:>@<97:8699=?<:;?=>B[B[]e{l3Sx_DBD>;98:9678:>@=<@B@A[]_e|o0 .nwa\B>==9;:6799<@B?@DC[]exUYyd[B?;9<<88<<<@DCC\__f{k,1**GRQeC?==A@;:;??@C]aww|M /v\CB?>>>>=?CC\esX& Fu_C?;=<;@BAD_czOLHLZ2gaC@=@><@D[_e|I"'%hcDB=>>?C]expO+raC?=>AA`tiYV4$  Eza[CAAAA`uiYV4#  EaDCAA>?B]expO+raC?=>?<@D[_e|I!'%hc[A>><<@BAD_cOKHLZ2gaC@=@>>>=?CC]esX& Fu_C?;=@;9;??@C]acfw|S /v\CB>>=79<<<@DBD[_ae{k,1*)GRQeC?==A:6799<@B?@DC[]exUW~yd[B?;9<9678:=@=<@B@A[]_e{o0.nwa\B>==9:8789=?<:;?=>A[BD_e{l3Sx_DBD>;98:879=A=:9;=;=BB?A[[emjq_DA>>@<97:858=;;=99=A;;;::7686668;>:9<<;>@=><>=:988:<<<@<755569>;8899:?=:<::>9766:79A>;877889;><;::;=A><<;<@>;99:9=( @  $:I!=M)@J8kyD[aYSQemyq/Pp",6@J[1qQq/Pp  =1[Qyq/"P0p=LYgx1Qq&/@PZpt1Qq/&PAp[tϩ1Qq/P"p0>M[iy1Qqұ/Pp  >1\Qzq/Pp!+6@IZ1pQq/ P6pLbx1Qq,/KPip1Qq/-P?pRcv1Qqϑܱ/Pp!&,>X1qQq! !20! ,4&6,+.8% #5*!39:$ /+4'  )-7( 1 -7( 1 +4'  )!39:$ /+.8% "5* ,4&6,!20!  PNG  IHDR\rfIDATx}egYsn>S酄P!H *"@DP * ŨLh lH/m:;;;;9{9;D?9ߝ唷<2+Aa(+ۥO:ff\OT̷MMRg ߻G.7{ox "ݡ̛'~VE玣ٜ.<ߝ?7̣+;:|^wu T"[4SSz.֠\˝]]q8PtC {LLR*Տb1\`<'ͭٞzNR1Of^f&2e0V3߽(@\5t=\hfB  /\6 5wY @{{( Ç IcĵXJ%hymX#b?i^ŢHOOh^t@ @52]*(+ Y9ͿٺsN/Bh p`Сy+捹7+xr2h:V1xڂWg%M WEf:TulL;|X)*EVߝK(r, 9_=8͜A#$qc|Z okSg@FGrP1aZYpRW7R%t;ssA=瑩5bls%'{]y8]~oxM<`aX?o^hAEg=qsXE_wD0r.@.YTʓ47k90 rΙHA)h;K=mIsža<8}D0"bA9 pp.>j@Z{4}U)2dD_^>UP >8U-f@vnbp=(  .zgNTC#IS  +%YצzШ\>%fhEZj5\B/~zd7 F0X#D~,f -Rf݅J. Qe"z` ZBs5*s?7"T @|`A$UaAJkX=?-!Eii9>0lIIs ^_D`z\w]5it?b1^{-'?A|9O} Uo٩ N"dτ}"\ávH`z\ &h+S??tP2JKmoDy7۫V^ ZA&4dA$0mps=+ &V1q@ t= T ' pLJ\b9WOI\@U,u% I{ ) ĴLBF1 Vͤ,FVՕX )F>~}}:_k0_?m5+r/'(Z9X@RJȾXI2R=NxI YSon&;ygdlb1OFJ`@Hq 9p =Q)LE*+Ix \x ; F,ODUP{^=Heyzj`'|u{,ΝA4aj&jme[=7 ZP6 'iRai.UoUb@5R"WӐќ\[coI3.8[Vjdl$' 9#Jx+`N:!ݛ;}/ϿԞ?W_Ⱦ,t (hdEEpFGV#aBzdLNP[rF]|`(E"P*iYנU' ؊LM ߫M HڳX:SuŊ倻v#lJpO%w][2XBI>eB CZ|ea{UWAS{c0 X (b1.ZB06RCe3Fj Y f573BnZ*6þC2{2X <97) oW"?!Veɒ%hT@Q %QYhH;xSE!0谑 "m3Uu\Ygpgх55"5D2:)' +cae%I H5 Ɗ=̚E3@Z؍hlFI8=wd@8"x;xd\`…bE$EiYL/n#wlRe]s 9-[Vݻsj@3. QSRXrڽ{&ݔa*8 EF*?I[4~{4qB ,gv 7"m uڛkP#4_}wIɱ.aff U]4C\;IT1}#=HK. t=&iuQ!,E&иepF&f!n':p-! (~pa:$I*iSaUY?84W\qlث^ߔ|>D,BҨ4'Zhe `bȣ m4s5"@ iҮ' ZOk˗hNk|{73:4*ӌ @07´;'^ {3RA lF#5Uپ=g(Ik!($T_*baa1$0 k"i =6{^rEe@9h{jֈ.l)ǍOP r/8#hNS뫚hV@si]Z:PrLĞGwbOxpCWL8K&zj/TC| $%ŝ0%XX,b!V[,4"(ƇdCFkN7L l3ˆn9 Q(i$apܮQg3,}c?;'$MWR#EOxvy/jC4Xq34/UW%" p \ڤuvRl s}Gd s0 ЮzQяCT+ഊ(LLYU=p D@I@V)r!#t!bܠZC sB ݵr#ߍtII}FZ}=pXיMn)i; & bIҥ]cZ0;kUm^#5; ڂy\ xtšʏ'+xu>{aT`A=@0FUT=-;<Y)$MMtp6HD4@y֋uWn4y"pӤc!6<a Q)d!+ qA?ZW"^ȢNcJMF`= -IU>p='e_F/,`iZ5_ӱ|gCɮ]A-0q ={rΕR$}nЍdgP+u[( O8Z;@ڜ1$mZdS=Nׇ`0~ S t_4dǪ[|nPP2<0Ohfhd>zrD8^<[Y_Қ) ⢅Bӥp\UҢ+x֙궛q=Ѷf>â1( X4p3N#t!O#i!YD3-#FfAƞ,UG{E`qF>r-1<@g3XX+ qܓ)Z*F{ƊЍ8,5+5ws22ЈU{bIí$ v2WP 5,;:Zؔ\qEc `8| *֬}pGDC$dـfe-pILhQ#Q5HtO4yÕ̞\B ~3 W=Vpxw7|e QAQu҃Z6VphJm׬h0c"՟v_ Ip{9q~.sܐrE,R "oxxyMڢ. @>78j GF__uzu):-xϪ*녃*EtH% jK4>ZrJ_d3{87f"L6!+0a!Qhuƿ4P*2%>KTjܑg"πu;vhRHj̒$U#Yz:sG2:u}-eSs&~3$ܨh'NBXטY 6i&?*hMh.#_=o5X&xkY(χ"PNb!FxZ~aO!iko؉ ]^ WOL"#7ܯnq,ٍu^w+"eX]4H~>1YJ>7Cf H7fUVIg 4$JlYj7$KV- ¸P^!kU22wX>`] ҍLmDg1e>s`A%>c`0/Ýk hO)Vn v_YrݸsRq?@3O{߈nSiRՇ,ߡqdM }O(`aN8 u^T!`Ʊ2VqbW^v픙kYoY4.BZSh6kDQ&qK*!֊{ە)b|TY ܟF@X#jԧ5tng4[GpddL324`d$PBSंH e!~ J8d2eˈ3QϝgjAf 1 զ$:?z8(%42DI o+UxAddך=672* %fzȑP`-hQyJ)R⠖=T :/Σ1=(tCPşU J|wuglʕe] )^{`%I*WqI&s5$K.B%xyY^''NgGvC6ǮwYٯ$qb\k͈@2?CN2L6 U/asgC{BukO.0P5ĖKJ >&)5"ZtgJE+ս Χm, 7' .%tarIld P V Ubǵ+7(Ӥ0jlRP%oTˇw~X'%JǦYQ#Kc reiFIcN !wJ!1CW8@ GE$b[3CnqZd}:c֒Ss riI*$-d5|ovp8s= jATr˄8GbŜ4pYQo4 ׯf5,4>.=RNz. +5T7nȴMr>F*-@3u92JNiT%I 8$@H`4VIKȪy q F^x}nP\IU a޼!yKE?Ynx6UCsPՇC+{ D9uq f},Alg&~\36)0KK5&ϭ;2 1[mFF|׭+8nۦ@s4avRIȦ,tpaꀻ>i%\@ ˂@%̸Rr%K(%,RT]H0@HˆmZ {zf `Le/?rp `տ>Yj  u6j@lV WOJHjEw#tkƆsǘ)Ÿʽ̪ !w#0B.ڵ~zF0O@ 0T@F4+=>jlsEқFfb=@5fBbSH:" >%~y!"%Pgf[}bhZεu1F &`ʆhԀ`chu AwA*(݇pKn߭ Ik<+cI1w}ʊ@r b?1[d21c%Çs9jL `d$aDx 9{0&ۛQ#hWW3TRՠ>JҐ^`! Imt cX c`#4\xE~v1rb Hֻz,` oMNr5C4[fMZ ;p0_*JBP2TzHMf*Bs|vÌ!3[[FӌܱV5{kO'HrԴcƁlԹAD *p_zP&,FocX`(X3-0nbUԕU"hJk<0 AƋ|sQi ł36>K\%AzwOS/#m`jg6X#PItZ/ƴg':7s[dupH2@hL$ 8ADlΝ2׎@(vQ*#"A{^f>kn>`o;h dѦ`85"& rw}FǷ88<\tI֒DVE 'I|G`X! b\F_#M<FRӁx|u@E" B %&q 19W٧sEV=?x9cp"! _! ccLA$bzn?[%\>IsFD8H 96 4~> jum9}ǧ{-{ Y$ᑯIn),|Ƽ`= g}Cj4zR רּIItv|8jT;[Jtjy8[JG ]|hꞮ׸0Ɲ+&ruy$BEҁ:j g:h.*O@$VoY݈$q^{BW 5k者eK_<~q}#F{AW=%S2Q,V0:UT~R*8 f:%X|9Dh0FwAg QF6"N"q6HX8崓$O0oxvΔiTf^\ blOC4 n*|fЏlvW>38{ b &"1$$ _F1\ \@/.4AF#"ХdiζQܓz˱83'JAPVÆuaҀ@3VrjBUAƔf3'=%yWma@4BhVp N=Li_ތb56qP"? {20F\-okTaWsY 5inq.)moX$p$O@_?ivyɜԮa0)F;+7(E)Eg&T-0Gr̃DqAG]O)(vNK; UmăqD8Ļbs?y 7Ky_woWyF+E!A8sOU(% :u- sfmNjVBa̋xZdLI̵ <CڤU'߻FDbI}y>]hI F?N Kd "+z*2>6Aٗ$h_q7{ȸhv%phZ]7ܗ! ._?PZP{ ruڬ C>r$W+ @ޣjo8bR@h$pEn*4k @hrP{ɯC3C1u0.5}Hbpw G4jcXWu3hLT2Fb#I#藆YGMŞـ^߯'N6%YwuFU _a247\ҽӒ'b$J}{{͞V' PSlcq[Hda?kn}p E_cEד22ya:o<ǜ;wXR98&՝ۤ z%A+31uDJծ ql6!`" oXHOn"wlz#4oL^ь!|F@<%'Y 1s5N[?Zs!Fl:l#;@ڽ`$τ>@HH,78*)uL!7 X.A9qxkusA4vy\}DJu^R=ș/*_Yz^aI\ˌfpfTA@TGdhV;201YoQKifUƭrӦyIM`j 4">7{迅V @3oЈg"*Q4iW`)z&ތ4ϕWPI$4"x8hsҦ%(\ƺkl):ZǠ*5[phEq5Z?X1;rRslŲǤȖJgה,v)5=\ZTE02sjc'@XQ~EHћ| *#E$A\icJv6J5nEV'!6c&\}ט\.);Fȓ޺9I]ǘDzB&Y+4"~0ur7BMU ,Ҋy@Tם SL65FjzPUsNA6&bAX;F@Lf2|ݐTEYzi?umu9ghBsWa^c +95lPXu'-Ծ {$"r@b@m"Ih T"4年B1$"0# kfwv]D/p~N h0EF}`Av°,r#5f0֚Q5xEAl@m=/z26-ѥD$|I {dI'5JXadLT]ٸoXl!V)Dɒ1Z}8NGjDZ'fRl_Gg83R MR=,@qF`bT?&|U@Ì5}ܵKHP5Үb@p|DCVm̿yk=JW (с:C`XzD0"b :p XaؼGGҢ;tXQ=gOyZP긚oXHE4=1A`BdX^AT5zZzAŏhdjT>kTGf'qFf/$EK`n&1~"?~Z}YD9~5#i^MeI#nvD6٩~I?̓Aס%͗u!Rz9ZXUcp6}+/{*]™wIe T~{M3t.??z2icǢ*c ~ߵF8,y saL1 !` \dkȈ{(2H-fI{4J\(n:l(x'{PVt 06a>g53 R(eTtIgP_ İLcFX4~5reȺffrQ|})߉oSTAYF'm)ߔ.tٌejT,տƿu(Ԯ7j;p 6FRrrKCb(1% 7@-ݗbVFX139^qEV9>AiM#тX="X#j^b&>|C\z_#??8!{4.߶.urΑטtB3XIžXlgS4FIB] `$b̚\<7,Z*T)(uI7Ԅa 7Q$yjS%G@͗ G*FYռ1q[ fGEs}{4C o# s6_$?x AAaT)gou|I=92~D~719myNYgIpl̋"{7E3McSfQA3%TT@\T= {UoJQ[WՂ*0֒:nII=A @⹜Wca"h,Yw.5L>ި#W2yeI+{%7ls溁:+ſ!"C!)H`0m#aD2ejѕ=B,Xk1FQ~D ș$oEn7!ѹ#r Ґ!ȂO5HC~7:"tYfN nƊnI4 dIDlXْV mP$DfwiB{6U]}0)ǭ-@h{🥿5ut gvAy.\{KeO$螒-}c~%]ʑGfd.Y!|*G!o;/LA֞0qF(eॿ#K.JAMjA3օDY$yP*Q"Q ؉=ܰ0t"/ժ$%' @nJZI}\#j5p @#oD?e,$rK 3H>&@#;+H.be!RzT> ¶ZxC(.h%>O⣱BK?>3Svȭ2ӵViٴisy>y/ Y]^{ez8/kP_c@PK$ZRE~ V7 7P-,e|߭?\<ɇ#?ހuΖtSEj0i* n#8[*j}ffk#q!s.2MZ"k<\|$%nQ{ea_T^4F s֑25=m x< /Z?KrG, ^k="9 2eR\bs)fĨ$HXA{UڬފݸA~LXeiZ-tŠ>nq\ϒnKqv].Q"^cVح0+#㒐y `PXԥV bI 7)6u*\Z.Wr:zF'j`xXM C}AЊ$V!MCn Cf\A.p4`"‡76/kl#&~3o4: ׯzm^L?疧˚SD4'xIf tTj DX뮮13n3ς?<<$X;H7H%`d +aنx>K豄ۀѳw$F/ 7BtFF\CXR&:08;]X%b[i iק V}͊ڸ֘-\)yqyҞiC:ki|YeyjTkw!`i@BHp>?* zbpH ȿmF%xPï#gmH,G&f3syZn\oJ9\.y'J۪ `y6"A&͜(A_T}6ܸ1mXW 6bX;gH1-.2=pnI Uš{˘"R d%i+`.?F.A(`T,jشV}\?[\Q4-43*d9)Wv0A01aĚCfG ٵPd9B}җ Hyʣȧj+;?['۰Nn#΄khi:7,q{#fߍ`nM ky=Sc,ҫzҌC4D|۰G"B0eA![C-ȏ|=R<.>QyD7{'un8儧뮼Ez_`>, ^ ,P5ߪ8ZĶ"ɴAZ{=a i%W 4v| J8 M1gҥ3_ղao }+!w>p}A,B&ZR_epf1)$%&=ɌI4:^L:A z)3.kCM?0T4"}W[!B\46U|݈y[wȆ+l9{OCj6UKGV/{\v//k.ZN7zu@PIl4<m+:.-GQZZlwPY 2k$H!B343][)%r[q:+'d5͂ȝxQF Iѵwlddk~jQj0FA $I E$8Rk^' VH #tXprU5`+#U2rE-8}9B 7d!GB .O^S1T}vpya]N:kp{նSsY!fd; 6 kBhdQ!h0)b(RDY/@!p]l|'Wn7͉@RY8󳏑/'c. dH4R|KP EXBR̈́+  MPԦ4c" ʏ#LD!AX`iyVXƹn92a{Q⧇+0!PcLyM|dMB^@7̵thINC~:0!-@5";n?_3@3z~`yX*R_ m{@*^CsG =$r@XG ͷh$FG=G}Qby&HPȇ ^}yB7dZB|+ ^u ؈yWyWޫnM Bn܅]GRJUȤZb2 FFk j k!kvBpI.!m|fz9=*4CR!|T NBb\D\qqwg0& Mj;몵&htAhx?DV#)nƝ>/𞣮IFbe[Z g1wUM0DXcԇ_ZNV)`˙ '`ѯDDeEzvE?*%.*@R~;b)!K~"Ă:&@>}`gf='\&o7x2QBc;h;6H0U@Z()vL3/}4mB,38`"@xPa p0C__<)m"}H$FƨUHPƅI* !HBPmz O6݌r˰&ڲEMm kR\j/ήV= ȿw[m%܄n~vqEE zRߘ+7u7FUǣ8v rVD>~GYRy܈{%?^sMhUvR0f*Pʡo򶯾EO58"|A.>u/-<,=zX4FB=$&d c, {3}ޛ!c H)s06Ϡ4 sl}G DG,蹈߻.`h }<+6, W.?*aT'HqK8?={>,D^GW=B zT+nRd >[ CJ0M?Z>6FsmHm[WUxP:a)5 ]R3PL +;o,˚>O!TE%Q!"?1qoVrm}]'78X`kkXRǥ+ѡo!۬ݬF\gb2 mu< $GoΚ͐- Bj#`[51?n@a0IOsilަ q]Xr"GuQ4='lgްtL72IY=RX|헙{Ny+u/,yyEcrG7˺ Jeڬ˞yr+a0:sH1{nyolHǁK 2!yr!,myKftQG~nTҳt fL#RsCk+ R: Ċj'#w d@֭h7ʡn)ez =`diꦛڼvElXLIԤxGj9;\D5L;WiE Hlc`80arkB%G3ӈ@1 s|:BCGSgwd shۻwR Uc z􍁳w .+xK4cyuaV_Ί"[dze;eMrܫJ14*}n9|g5|Yu R}P<)drΕ{iz|`[siLI񱪄?w{\s 27zzeby޸⻒{NI/EorsnYua_ #F=yU;e褥VpMY|9H,3_<*kfk aUcdC.Kq mOxɢa Z*0@w~A*e> N3K&1.lԈS]sM5%@M-/N"P!`q0`XC3"$ $]QT(ŵABn!'֟Q`vo_fOuU0jVvoz59i΄[uY@\({w_]!K]qF)pz9Л0H)o~B6|:''ʐ1"{}~Ofn3ΖM+O`~:y|rXΗsyƋeWn\$',> 9QnseQnF7ʒ>[ a3|ƣ)6AL-cD[W䅯CsW3km؟= 7c繽.BUxNnQOk8F<=O}* $x6$Bb[%HE^D.B@lDIS^jH/:P "kGW+Q{/?7Yo|Dnzý+gyoLK 8(^)#ȉH5bvȃ_'>!roV\(u\>-r󿭓ɩr~rWeLNO4ewa쓙҄]t_Y"G2_@z^Mg=FFexfDޕ7{F%S0'DӘFȪSvK8/dbYp^{T+tN@ڭJ]PV$έICPv.~ݨ$Ց*g)Õ)l|& A,i4.͚`U|N35">'WU`.TlXj3􅵬=;:`[Ba [E7,뾳[:Sݷ˾M>o<񯬓w%M !ϟ=rӒ@ޞHvzT&ުN =?^*ߎw2<_&&~a45OO\ommEyggi?nYuF @ua:$C%;i]wH/릤/ⷛ=Xli)V W)`=/1Y"j5)cL؛²eSsgSPj68$% a#f$dtjpVդb4%]@*@5xf*LqErf|73܍ y*d(eej 3|ݵCT c5^~\O.H8 Ա82tar|LjG.|~As8]dzzF^}+%- +}]#ݎs#_7 }|hm '.yr@Jmۜl%U "nBPok H0MJA, 6!n={ 57"ȏH xjLRtAqCCZ|c՜|6Eo9` [(P?wD-E~ zA NۑmW?2vg,YL޹t᥷w[:Unu /ms^WUl6YN;%]tٴq<pd 骔rBX=C; ~9/:m -CFgR eCS(HT#MF}BGSww 6[=;k EI][L7[ trOMQ4)H=T~NOQ<}KR (4nC{}*k? uÚ5Iޘk'Ղy?".!d6$MsZ=ƛ͋$EUzjN:p N[-Jm.qz Pvϗm;evKG__Y֥k_INx! +ΐw=8*ɩI+5,\"b^%/:Ri-{~TJ^YҾ/͚k7XB`!ߔQ pj(U)2x=~ǎyXi_ n5DH*~u=Vem:*u${ka\.,[p Q ݽ[ˑn@8XdkU"4t:u` $*&.V=b RA0.m9>ޛ38 y?`tZNV膍S˾ZӚZ3=DpYKQNi_=&?{P. D  v@7icD?ܻMRɸ_}"??5urs]v3q*i[t_6$5cLR |x52*[s6Z0kuAC~CHg|aeL~܃^/b "lT@?ZQpuㅅwrE) ĵ~.OX߾o_ fwmF墢;q=\홬.k5:Gv CϺ}Gl4zV)sb@V~l7<=&CsKF۬!C[{{ ;";wn 2{]dhRb3 ~w~K%W8MlA|RotnញrYH}QeD4},Uft](ۤzd䶌yyK罷ɶ'e/\}*I 1D|貪gKzӣ|&99YD炡:m˙6Ì*D~ѬpPq0P$ Ru<~B wz!곣{ݹZeJ/XP8bB:{re8|PW b<Inrs9몉3F1NGlp=}?B}YHa@ڰ9KuTJyT}ӲWeO7?@.6{niMrܷvܒO:/JZyr҂ǭ?Δ>tYO ʎ#( zkQQ`$ vtX77M?OdCqU:t`_`{esCf1  }#)Bq,8@Oc RwzwЗ6P "wkm9]:sq-]8OGǸo5V{̧EiAO`a1_u~,AZ?]yG VQ?@BPi~YnyY**ib@T_YU5.ur僃rm\}?G.W_X'x%8qѨN5H~VºPZg -G6hUbf*2 IЈP{]d@E Wtf!"B{;P_swfn1HI['M !`-T_[#@'#tr|dT\℔VLGT ^p]*-0V wxf\S(0b E/"ǖb Ul-2zaڍcFY|WZw䫃'KLɇHx||ܹФ.G/\^~l(o_{T+%W| ~ATMv"ԁBP,j-=<:@kםh ~r󣀅V 1Q=ĵp0]2&:(?lӽJ٧C219%ʴ\"[ܾfvW=ݽxn Ɏ;o;]hCT0 `?P`mԈ4 nn#^nA0]Fd orb\۶PsxF:q1 S8Q[mhD0(3Dp(%hhOѣ>gʼʔP1&s狖֎,FdhaA4rJp^h98 *Fl |8@8{2\ﶪoaL? ~*'GwUfn{nɲwCLqqڂ"[8#DIN8V!~3Y=Px"6rGf@+ICL:EG#!b*9Z&9nCg*$7w {Q,\L:{+$8̖A&S F8@HGk?j쵵Xnff.ĭt?ݜtTkU튊SP܂ @VLI\f E ر\ oH-P jVF=w,!Dހs' @oy\,K;}̷\[Gs}WLJJ"DхpfT~8*.\7/4 waMe$IGxK_ 4)-\sqCX8Y,Õpӎ]du,DvĐBp_}h$B>zZ"_5z>mg&2^ 7jm1;G=mTv =O% {>[s|F,6 Z*/~0/[1&Ir֭}ds}Y.djFd-ph"H}R-?$ \tٖ l#=P+шR{V 2Tnq²u* 4"]؂ 9&hrB\B7,W`Džlsazsb+j^%RT5;aN 3w!x3 LG:K85lk lN8z&Zn(vA=  9xH2_U9 % _TT{/*\~?Jor yO_Kpa)ɮs$߁H2#rke_)Egz[ dK[ۍ!¡"ND%YL3t߃j#Clǹ߻1:{죯>9p~80 HȖZFcj*+`lZ{LTQwFօI<rKE>S36JIgKI&K{e|a@j?ªY`>ms䴼eiߕrh|twϚ/=2Gkϖ55,ӛ?Xyw֛lfP. ~]мw"֢dз]sc4kfds +s-E 5?46uucɕ@1 TQF`)B>%aaN&,=]h$ٮ4l p-wΙAֻ4f ef yYK$ŗ[a8jj!QU-Gǥ|!;受$yoXy>[CWGR(*FVx)Ks>|ׅ/$ <€nq'Ieȟ? */;GaGfDaylB&)KxwטxCCe;Ab}/JAK-@m>93f92zLf1gnYԒGL9奻#N {$[e?&syE>4A6 {$@aQHlr?tWHarh'2q`Ƀ,~_W/[v)3 +>+dgrY=A{~3cDݶLɮ@% XeQ#?[(7<~~%?e+O&g_EF/ǽ"rkú[oῡWv4T]Ci?d5ExCfQF=tqsY}+Jό: 1m{8W.5 WsY'Aݔhq,2JDb#79Lԁz:2D;%<})mE^kƸzdPuˊur{ AXcNfۥ2A&SG;8ON],|c/Gn 2 ~\3YHQCACv ?QOJy}RaEC/۶_z^y!9qrٹ#:y?a!ZiV,)7՗bIAF.Il Xf!_Ge,ed8<:+`@'g|eyɢB|+M\|1 4mj)+Cq%03=nϭkvX48EP\cTn29,ß/p{~9|&wrY(#ծ;MQ.ޮqy7)WN^'lme8*/<ˌ`tJ-%oY*߼_n1?x|:_lǣ}\{܀'G2xqҹjjA0 =mv (5b[S1LB]I)^jȓjvV>n`]6`]}k0ŃfK&^Zlwban>61D/s]%9$8fPK\C>r(1/ <cfD Gʶ,-'/59/fAcSR蟐fQN6^T>Ey`XOKнҵ~Z6~y[䔷>&+~GrǙgF ]bH1ȣ+s;{W&WUWU]kξCaw]FFwQGAgqFQEPPv;IJNwҝZw꽪Tu: WTիsY" Jbg`6pM?aQca*H . 0uT[f~SBj| Y5TyKP(<h2?zxtw#EsVk<{:pGS pP;iד\K7a'MaJb #BmV!YFCI3 ǷhAfE ?'RoJԁ_?è(.9_8ng.|< ;JbEOpm (vls1OJ?'{qҏ4zupqaMxa|k;5=r?HcLE#>~Z)-h)s\m+Cb~TC].J|OkGaSUHLQ*AHQIW 7 .Lk Ȧ^ qKK$Uo瞮ĭe$S<>nT (Ͷpc@NKpbVNTngnl h"©C{)mxK'MgnƎ;Rk΄cpEx%:w LwoAi} jcNTZ17e/.q;Iܾzrpe F  R*ѹw|>x2V`kܼiƄQx ܀@+Q2r՘9XjMvm97e oȜ0z%[nº`Tw&(xVߟidC kO/+) F*yG T(W(JSVz2|WzQY8m^d*ϋ[aԶ+} BgVgѮ^H- |oG'}"DqoEf"+0K iti a^o+& )0pR p[{e)Ns at/w )/# ;VHs'<ԝtL? H~y;gގW }>ئМn:Hc{%帽6g'V-9Id7KwNK[ mE>z,n|kX5Njs? 'tti@?R ZP؇n8Rkp S(YO^q~9{ (A7a YGjWTJHM8Ce&VߙwtѴYĝݐ` øf/ a3n۴]*_Oa˖}1cN<-I|wc…mu .vao+?N45v(M7e6GuY N"K? }Bv *4f#'=K`v˅V d>M_Jj]tΕBuj?tK>IE\$54 YLiѝN7.uR| ׿F[}~ȃL8LH)1sN#yjj|}RlY~* ZZDFDJ-p܍; |sKNamIXYYG_߲ ^^e lz)xqT>D)ԝU„w3-_`ҭBS?X'p^WVA^ȕR*͡"i)h""K,c} sN2?Rb-O4h)\Xɝ&/>`9E#zWxx 6褽?}E{QyZZL= mDz<^Xߜ\)߃3kUwK1Vm >lغ–oL|b\c>ejAWcUE@  gpTyA@-j3馛##"b6궶HRO5"4tٕ!- vS\f?/MFu ._m~$+?p؂uO`O*_܏kGcAX۾U] n ?w'λi\EKw7S;7}'+7O0sgeIsY$9piU~+g,! GdKw% !(wKC}r)2;2"J<=5{,\.sKmM]{告88,9>fE `4`KEMF 3~\V1KH~?Ck~Z; 7l #l._kjb֓]h8 = o?_ gْpc]9Ϸ"Hʠ#$Lh *cu7$|)?gU_H-[LT3d.Ĵ2sRkBVy*mxSh'!oXF=^i/#\،D˭H"2nBEGAnPGΫ]gZQIi WL/nia`ZgLOO+Ǭ|6X@Py%5SʹVcx +XNzV$m7!.h"ԸH51 7ɗ_Ai;cكVTdwi2i-3}]EI CP9|QD #S~4Cgo5{ԬDZ7}AQF `c17:?*O|T/K6>埅%pe >H8f7`3p2rt:6|O GL$ēc23~ZC#R\vưn/, A=~N@M+*G.Hsv`nTH]3l]r{LvE'x'&Y@~+Aw!Dƌ3WjO͈5ңH<=gbo]EL\"Rx7ppZP}[P19])>@cil_>8W W Ϋut IO&nx{6$Fp0j}%z6~zWq^׵Ԙjg/F-3o+;@eol1^b+Cf?e ҋg*PwI Ƶгyp(|y'_x^8\_޾+C}:oQ]X5ex׌G|^pYl̲fi-Ҧ4 ҁך65;9tpf+)}&fZ[J{ejLi4zhQH̋Ax$3A7BqͿd!*;.> x9ަ j_;6_^wߜ^wmgFb}*տ-x#/){XC}*ogO?nGrP3t#,sAgL6E^cg `8G|j^ t@[q $gˁ5Ő pjPN~zմR.Wzߧ_Yg>/SyǗjY]˗BxWifr`gP;Kw#Y%7gCا)e}xZNlv ImFitqUڞ˞{m7Ҹ#u\Pʛf*э+1-k9zj=++j_P7iy<Ǽ)5?,EܶvJ|("1 }L})ƻJǧ\AMqQXC%] ]4L&îbk]^8O&aCȨ=O<ZvH? Ưn ߼# _M_)PK r(> fIDmϬr^'[Z>Ŗ/}_O-xʵ#IoוUW<4${&P"" Y+o`5ee6t4}MgB~ɷ8gH#.a`.Azsk훵o !BW^K7e޼1x8<ޜ#Ŭ35sk2np,Ɛ?WoeU3 vK 2B^nYNaQ@y!ᤫ |R'[J&=]i JOMx!xie-lc9cOY5Fӆ'r _;c*y|0%ݤq B7_Ķ>D- s1P6~ "}Wo;s8DLOw4JT9 5ZFq5YtQd3M_ 'P*HZIڛ' q{6L3FMS7qXGp ϑ H S" NIr­@;!;DYmL&#ԘkM`g[whD*!X~w4anC{ ᪩FqTu#ٲ*>l}'J:uQ Z;(0Z۬6ﰰF.)_w MDm^lZ7 ˺B,^=(Q.eGƤ g>8@7J(3T\–u+me<5rR}%6%԰&a,I ( P;i`Ir3fv1Vt&4C :i<|UWRK~}"F!c~˴TF#@.D { wsFO#\9DnB5\k(nLFFk/4 ([ۊגx5Lg.P3 Ww.~\E˞7f\:3O=U#2SPu[P8 /ZˬFeA< TX^lʓX>Vf80zt=h. e , `M~ @N M*'P{V Tq[g\1tNMGwpX^DbpUS1|=/ #R0.PR3?񮱸2ԌWT~w$ ZsH]ݞ&|G9 +pN`$A@ 2R 3ȑ~Ni @D{ϟ5&  S":!lA۬'.mk_9X"deKQC  #O@PAgȳAF +MAwQ}.sl.:„;u-(/9=0/_k}}x#.MZreˡ>7ͨ+q/Ua·ϷU#;) %fk CfBƫ?(0庶Y1 gي蠵U tc@9}Ԙ (հbW bn~..snߕ_KN6MĴ3W#6_w*ݷ -X?.}Pʛfplt\v$EL-$0HMxWi{eKr`)\/]x`]]Jˁq%"CʁY+cdёKVf#l/bǏbVP)~]ϕ$D{>Mo$ߋ]*./bohn9\|0GuQ5K#g~Ҁihxz9pt v9pd o <d#Q0#%E$a@S CCyJXK$)=a Aߟق|SeQ=B8_لX *&%܃!,n>i뷯yTCş ] Ap3q7wr[P>fHRi`% B A2IU#qP$Fvb`/%@~%XQQX##YX&ZVߥ%X Pu y/;ҫ)AY%J$"J[J䵶Nj`cO,#@Yp_ W aa`M}} ܘ,jy8J0u8+cf-h 8%X6KiS5RP5hS6RP{*) r{~fa<d'ETzIAY`<+x:RRPj]>)ρPcdNl= ]?,^e+^=d<{ƽ+;<ި,Ɖc0n7kǢp;|R \(J EO8jP! ? RK N*)/VS*\oB:-xĺZp^i4@ NKт7 ɞNDFOG^<$_J NRӻJx<χP]]LϗX7?܉׌=,-zLJAViCA10PHZ pyf Zp.X NFɢJ%}-An b݂5P9\cmAJJ͍)1`W7!ql+ЃI1H2?]1 ݸñUX~&2[;=6,#gsn r0cWD٨9^cR37(Ql R`' s5Q6⪼ k F2[ɍo 59|k0a"v;lZZ}`_VXl\[:'a=J|/c-G_ǮZ{ٽGO:iy9(l vL5X,Z}[^ 9 :~S6_3(*J_9h59(Y A<栴_AOE^nJ['6a]cɍUp*'eSŅ>bQ qZTM5}j\aA+wa+>93̣t@f wmlΕ'K+>r ;MC'{{pSxyʟYC<D Y=8K&yۃS."cBE1gor$6!L8Y]mނfS>q6n7d}.f ~y-W[+߽/zp{<&Wq5NÇN w"xk% 9ʲX'E6-1'}ړρs}~@ @ ԗBϜ>tQ^۷`(W`8‡V/{>nwCW򚚤={Ci(c%A xo5̊!.aMYᷙ.wW\ցC҅iit$}`s 8](|<[r6>v(S"'?y+}a9 =p U5S*‰Bռ%<Ϧc/(q L H G.?S}4AS P` Gmߢ0f >G?\16,A5)к):2%/ w 07Lt#0$V?r~>zl)B"G܍AIR;Z^v!޳3<<ۄV ݤ GaNWmF[[k$(G}x]hI\'P8-q#M;!kvpW򰥽fy@ cr,\B^x|e9S9}U̍fVr|T`0(d2CkuPh43/t)vn*gي[3xhiؠ^׵B ^:Q2҈Ah2WEE5jIc]2=فK6,{=N7p]I 5=?B?pLX퉅 h&Z)tN䠘/|6cT\88RIs3pQQexi_@xՅB8 HcqNKJ1f4d¢AgaakcՒۺ؞߄ [j1xkI+#XpYOg,#:<+`3_h¦/s{sMI?Բɳ_97L04T`"oX+ NX-#.Smm~Pe 1j)0Ft.\@I"0ȿRA@X} =(7ϯm5`B=H/fRP"ӑ," '~,d*(&`ͱ6TLvݍ_+bƗ7"Փf%@=H,6n4~r6Ɨ8KQ8}o L/*Pz<ycc:ڍux._P.3,xqw"y`>ej V0{uaAk\p((Z~}f/q cuLcspBϠpe̯K>ʋ-;giBVB`.IDHN\W̞_~]Њzo7: % vZ|EӫQs5%*̼mzgg^*@\OEhIˡY+*[3@VEcnK%DZc ]`]U6 <1e<un0G Z+i4sr_ ϟ2Sy˘%*k\cb[8NҏQ(ã++73 FJDڻ)}p h Ar"\'N %V9TZJAGSh7&x>l\9})-*ZBsP"KZ6/?~/"o{ 3(<~2x)}f厖"TT0(3#dm^HV`{P׊،"4b1f7b,d/ܡ)#ל[>ᨏWe({FxΎq:AWZe(؟*LA 4d5wP3'OsE2BJU SK 4Ũ7L(1W4NZPiͨx~1 m^3X3ٌx-gԟ7i!+5-feXk>t !o)54)YE6=)ׂbvi9M/ 6(0PҘf7; f]zG"pycr4a.1"M@>D@eá%^e% xuD\dq 0BL>j.2 Ǧ )蟛\\& }pB @njcA()'|/@4N 3 kIJ"HrKYBGP4\w/.K)fIim^OK5l~h1oZ1؝3 7?uH g`΅9ISOQ_/c[8qn jTk@СRcFs׮AU ANׁsU-l @UU=5&͕NiזHZ %8a6IlB_S TbB›LAQP17Gk p {зjρ>|Vi1+e<eW@EUp;l;3$V"QB'.@`ن}SqXe#)R{ lыf.bY%?ǝM/@(GNs+,٠nj}0Q|g\0~<o9 '"bNӂeFEK. IG I8(8hÃC E&v 3۫Nq^h(AOڂ``* 1 SQ\o)ٯv:QZ^$ mXM\wVG}eB%g߮} @RiTx;B#)؎~k4d >"rh<ܑIy IgE–iz ˰0NA\1X:4?zRp ?~ {OƤ3pb`S7~wd6" skshC +RP_ח3K0W.E@wD @W{ A94oԼ|G!A6 ^0*I3]˝H %11 h0xص~jlJ;~*$+ Kpon>3kVvwFγ6T{a4mց1)D[dvD0H)d'cslfuc6?7/ugG`Q'4?B -k&bmh5{O'>_juzy(d|IGrRNnr˜ p G1R |2-i1jk0F( 98GM><*$^)Ȃ] _+Ax`!ha)ז!Rp6<PU R X^2xO60R{ܾK?)/5=Jk~j_]28l4/ǖ{;q[a7` gMu_hG5Һ+=(Ux| *y,G]k#9-7>5vJ+oʑ˲xAJ\w]v PX#2 4M={ˏB(T,` k::В]`+6n[HQ7ѨB8gF/Srdn4V0{ļd"*NқPaHTgal *`!&f> VF(663AiFt>6]xddx`XV\(V؎@Xl1b>]y$ WtM8gipjs\8#2 T>WM7U=mۤO|&hhAK3pFH~˧$1?Aw\rLK?S|fsu[(7Ԯbjw*]mPGM)1ĻOUmϤm ׻2*!=Wx*BOyy%<-ѻ9Gvm+)5/ʕ'Oֶ]>>GcؙH}_>''3 \oj]RFt. 2<988*H),)Zp{*b9.+0H(Jd1nhHXDHEˊI_joEVQCx) /]ZsK4"EGœMJx,sw]v;bQ9}R`4HA.Bbx`z.F;|.0@ڞIZpڞ_܋Lƒ1ذA(7xlgb9 mϘk85wW 'ͳ݁(J1~<ʐtl;;s݁ܔϯm3@&'`?[ 9rQr 9WJ ЏӇW!&eBt rB3d~mh`kk##QRxRA+=A"Mx~z,IZp2o[AV₂A[S).חoϣ**" XcP`HD`x/!.@w^*p|x,ƮvA{aohOu.F\s qo_$__[Oŋ[p<Čh>.hH#7+-KLOkYJsL mTk/Vrh$ j`=u┕TW';|!Hed6ɵgU](Ÿ@ *S92IHii?n#(Ȫagg3c2¶9Y`I!Ic ljMӨ=嵛UZAA"ҠUzEB؃h x1m{A8SG?q(7҂>)jU%Vl~܃<3qCƕ:dVN83' 1L xeВJA{`OYW}zkDjRҨ= l1@WOQcVAG? 4q5ևdďK~$yڎ2+"BbYJl`wy#N1[N­wavt6:xi!y098~ rv{w**FY N*%LX_RCύϜsV%Z sAlM*u+\}S)<\ih Ĺ!A7eQR|gʋz}9s=dzC]7+([sddq 2Akb f;>Lv%ʷp>G213)M$Ik$Rmz Q$ !;ѸHʰ D)D=bW؆Dl=6߻A?`狭x͸"M]/bp{JQ7O/ѵP@ts?hLգ@dYD LɐÅ6ͧ=kFJ` s26u-re"LOd"&3MM!qAfJf;\/HN҆!Z4%ęe"`6{Qp؆i5P8)ʖL@B)UEE"@MHX(Եb))a PSP%o Xt H+}Yg9d[*ńTbe4{i@V"vkADtlKmoD7ځBqK>,\-[æ KKaL Why -s5xAD[yϯT!a"cPDk[|\hQ+ ]_ll~g?s]ǓU𤔉+-\cY^-ׯ#TFOA>BDBh^Zy)ABQ*@uU".]KV@O_a>/DwOa hITlmƠ!y|G9f <:jLr3H,$1fn*WOoCpKzVEE/3ّQuV|+p7`B(u6LJmlϓ+֤ sTGFkQ"Z-Zf@8Q( 5(tPp L +qO B/%>>Np*Լi&~vVOރ]HRqY3 /@Ea;ϒ.J_">,LYLظB4{)ŸW!__[uA J 5Vğ8/~(G4/%ӗQ3brqMF81pWC COZwPGG $ez9x}ᮝ\tQ _0UXAsIW:}B<3UL:G07 Oذ @c 5h ʩO,!FiؔVaZ=Ș`#>H|{*J3c))i}H9opD ~>ʀ& W.9 c7d\d @ӂ% XyoHGq$/_i)EyiG[Ov YᇓWcʵ(zosՓt\o}uЉ.oU ʛQ 1#ZvR C"̕ a-: zѤ-/Љ-IƁ/wHAQZΫC3DcW 4Xj# Y>_!VڙRPD% 4Ÿ[s>TĘD64bjd"y4}۞8jjҶ۰a_FGֿ-0<&̂wߋ?ϬZdARw㟎h?~ N8#Z"5YDҚ r_f+ED]D:0aq){t5'֭ê,ܟT[6cn9`:/(:r{ ph Ju^:8/7X >%'lHӚ*T?U#?ҁ;oځQ'bh_ymֶ񖥸,L-Gi<81UoLf}yi|y -BY28g379qR̗ %¡˨LZs~iPPDPn[ZM+M(Xwޙte-dvZ1sQ1]Nj9F;8{?xϤ5-zӋ~]7ksCBB`s=&Gz#֚gU虀чzAZR9hOJo|mi/^kXʟͤ+1! N~/}S8#[rZ4)-{po[sޝZCLcL՞ożKĎ**{3av{J4ahkx{#ڏcG-`KD9^| >g ?Ta4:@ǜ;\ +J1e[>r@xMsKv.d1KGWIC>L!fd u*\8o24ZR-3qUKBKw"/ mrYAN@s1P˜YعI5izqtbϴ`#fͦ~m;>ꯀ}4R))Yv࡮\\5)V@e9A;yP<@ w915XSq_;wKGcLei#QΞBT_bx鸻~?\(]Nތv% 7M7J%Ƨ4T? 3 (+3L3|r2~b z4_ 7"4^3 GHddlYV%$׉&Ϡ巻ØO(#mpqf 6j?QkC}ӯ|<'KϟdXi@~|sn!JQ&65M+(/r* '/03pE6e _EiknT\ڪGB~&,o_W Y3P⤠Dg-(gp{HpMP4f"ך^c]cQVيKǠG[܉͉e"TK$ `>~7{€3eypW06ڀ^ϭx%v;1کEkOZʰhw{vso\lX;u*hA"G(R_׊*eМׄwM~tޟNƨ1S.cһLH~sOz}ۭyA~u罿2o *7KP,AH4- ۳Y9=\|i?/Z~ uX >J>gWk}ad Fk\!XrsML @fQmR(UsYs}`b"P|@wRݖ1W9#V 3Tx*6)O-؃FR̀r:̠Of6 H4{!x h$KMzN]C.ۄ±ܮ cC^lӓg][mmFJc\bsk\ &jnp>}AK)/FD2eyؾ* g>AT6T`ZMOImx!;8k\I2 f䤽Mb~̠ nL%xȕn+1:κ~Ol.azmħJCn[nGkk^;^Nn46c?m.04ݲpsvau0ŇͲk~1Q^%aw.!QrtTAS<L_i3@A7`F Aϴs)`*sC4N|{B I?+<.۪?R.T EKLTh҃3pzAf[* ~&Y'=7W_ȣVT,L-V||Ke/+mC$ ¿DWedF@Mw `] v,HUPV01^p R $iT7B݋>s>6Efc]bk!8fnҟEK{P`>Dj2H,?Ff{6aێ-,zMN3b):ҭGVX>x%y ޫdue|`d` K tJJ]!V^\?`(>KZ\h*T >K/rdkz .APfOͧvL8mK3gd ȇ\| @.lףrCmI͵ʦ@Db Tr[Zp~4'QwwDrRe[V cvgR뎫ôbb24dV0 (܎mw=xk4;V>fQ_;u&™yVwM!kO3ߌXǯ{=!y <̼\3-B^WAA/`e P!uS0/C vP`␅Hۀe ;iUWpfHH ¿?|)NSZ8PCI3&A#]xTaHUW f3䤥4]B!UtPfINWР'>҃~z 4Rd`082NXHpRu IR1*NTrJȱ&ܞ#lsMFt*⃠B(<36.@s#n 6nh_ _/t̜r>R>s(;w9<ګVQM\KPD]Pl_s5/ op:ȳb Pъg:r)9rFT"}0/,wF"z$K3.~bmL? 7CᾺ/aɘ&~530'J%W%m +WF"D,{r1~pRҊ:4HZZ@~AevK*f^c$&fhpP¸A]o1g)܎sp+x)#l$) ۙ<|v|)οn &7b2\$nKҦ1 a~,zSM%<|>I_NYqDCS> zp͖)H@kB?`gM.;/Շ<2 Lkz&B57_4S#IAR/r 57A8~,H n<8Ae SIu!{D~uz!\  )1ioK 7oډ'<4jvd|s/k%w~ 㯂'dФOZy g"p^ H}zòa¨݌niq !lΤ˼̠ ;b}q"Į?WRxPTeUqg--- SHT0 ajn [пNǃ~{8b1cG㔙/ؙ;1X[؏ bNf,˳dM bOD>zR$#YP i)CΙAT/'DGrIf*}#*L4U~UQ .g(; mk3}~69+i\}4*ig^BpGu K>ddK'*% Dח@_0R5?RΜz]?]| dN]:TUj8!fޅ \֞->`ktyߌd>h ,0VB!@_F l"~{^8^ e}"uL7k f21 6 4t`Wcb|x /mVM@ڍ0_:GL|Nd%Ck_-Q̑oWyPd\yi}r(7p--.~ÿwOd׿.ݒͽ9X#pZjU~?l/uDsЄV$k77a";wCO̓3m,%bۦ2mDjУ/b % nh䳘~DEx*Mmvk~wܱ.NmͦaBJ{m?5FN'0Vz)xiuI"5kҹ?jMJBsVV כ`$s+հ]€(}Lkr*|q"޴]oi^j rkYx#êcpǎ[/!7,cVLS_W`yytudqB.B3dB0! ] &mZi?041ك6X6!ƯVao5ܗ*B6ްU~> Y0/ye &nw!1`0 6C[Om~O`mE|荶~0:{%:ǡ 6I#`pU:\ % 2`wpccGپfA^S n;gj!kHxZF)yW3"˛3W^#_;.o,ڷ~Lo}N}e;.J5ýeƼGT:7ǵzaM r''#Tkd ߧZ:Akeg8AP45_{+? NBW6T$"P1ꏁu CMc*4ijpr+_ }U Vݳ皜;TcoCF#>_V(me 2 ]g`U><8+*|9YȈ?*{JWo?9u'='kpUZP_SJ-W1懲mWLۥ hXS5#18jM|ˏt˞hS@߿Wb)F>ۜ~eU w`=";ZP#IW _Cfi0jjO^EݍBBoTjRӀ3~xX/Sʤ,  OH5Nr'[OKPYY_VEK{oue=׷BᇓRĜ%=l]O`5O`Yp05ƬVcax& &R?Ip0,1Z F6PfUC'dgugFUk8a(6N󙶣Q^kLh' bN]ԢV:< {y<ʐ#*481;.~#s>X H`D۔iMO6yſ-{ܮ_$ح!2rqRhvQSբ =mhUWxC:Gå kC#մh,Sm.(xM=PQǂ;`4 mTlmPuuדA<3=IJ_8lpF[Fg5gxJ://_-8_04\g8_E s@+Ay?d/(P}T|x|K)IH PWF~en- ʫ?gk봪.A%a2>{C𐀀!@TޘH.ĄʔL !h9_O4IJ*,NT)1D_vyGc~\WhqV71b2,lĜت8ly\~?W:d@!397 F`h^P(SU1mUXKr +\'lY{YYUų^(RbV@)ʴ!yBBUw3/Op5⩼.\ &g`Nr&FnOCD1U>ES`. F+=X@|WC7Ċ>62Tpl'`R" )?{9V uŠԭۗl qs(g7LJFqn *q 2ta]Dp#,ω )_+vI;uYy8K_ϊ D@ &]0b1O{\1W5c#Fp&9h0Ce t1BgSMцM!`)AɌfc:=Xz5X><LC~62aN8I;Z,kE؎Fv 41c&N=e\sb6U`]CcoX% !P1} Q< y୻?pLRښJZI 'ٱ*Cz)cswn-}} C 1k7b^u*V@R  㟔_m2w+6~a2O}Rҳ29yL!٭!\֊X.LJr_0Pw_-Ö~W! :$}?.lSG 13 YXu7UmR@>>f)>w9BpS\YTu&N" 0e~۞,J+*wP(uze{U~ȑ0/qڸZ^T!e.bal{\+U~H2-@Pa&<(o)]='})-h{/'ŚFnK.P 6D`0(YCsy̒0p]w]glOaR2"#81Ԇמ",@X?v))``)$ÏSNMi]? f&Ґ(:&+krB#=xtrO'>M~g7domlta!нeT <B&PeT㉔h8*t^,2AL%-ń~8x:G x#Ğ WC- J7z2B)x`Rr\&PE S|I_˪\P8gV:ӓ $36o眢aOhJD+<3T[oȩSUf6QBx2u1DBAьjMÏ7BɄj /@#Rh2 GΏ!*|ſ%75WxaɮM]5Rvmtj2W S={I5;Zܾ7 b? H~aQ``XBi[ejCUH DX{0em Ę1E7Ywl |q?*4d…%^Mt4C+[xb'V@d0i]m.':koA$>t0lI6cy YenA`>˴MW1&@84Zl , SEoO|>'&{ nʸ7͎.0|BLo0=UXEV&9>,0lv"Y*'l/,?n32_ K!mqkYދ ,C.ĜhWqR2- @>bZ&xfE!`갶Pm\tf6vN)zᆭ0DM%2U!Gޏ|9MRئ(n?+nqӟvqw%`\ h(86UrLxq2*= N+h^-d jv&wKsBi 02l̕q<ض*C7Ozg 0Il  r Qb!Ah?X#h+eV'.Q[DwYA`܏'tfjNʸnus稘/KG$zD :>W|Vy,-.L"dX"M A`KpauW޽rBAB[B S+O۱ĤgUɓu$gURWjq'"y4cs1U& {P)CtLL hS.۹[4pL@<2bV#y%bs \ц.$q(/f:!, "B@jaoꋟadsÄ!Sb;HVD@^P&al&ٷo_.'WA]l,DhsC(tu]>6oCi D0֔Kn:4G1LW7q rDy:{)Dam3804!]0&F.ҤwMR ˥hʣOsiRA~df&E"AARNV >Ch,DWz-Uwr 1?=5|&i 6i &0K;RZ)}l؆t13s@F=nDŽ@ש.3mh?08.h>Ҍ*yY/y3xSu]'@NA&tbgch!Xٽ{T=CyUTn(v^4{l(jއMK&>>6lKKk{m'%üpIA:X>f.H=S>cퟗϦW+P=}hEy~8l_3qG!T0jLYUhSISu^jk=//8H qOJ`…d! ch -ڹNcl8}zA`d3<c'WqX'j @W1SuM=nTSuAZ׭H+x]K]?~2fQ[y(JHakth^vڃ<%z&64Js@kk.Wg|󆠅BF&p !:1\FaMqdhB꓊ciΧ>?J* OjrLl]9#4 \ŀtmÔ\?_b_0!m|ngf3&Su4)ea-f~C 3mYpu>t!32[]uMPI[/DXw!FKf.aPH́(qثZ@6O1@}:cx sE˾$׆cu6Q -OQ TAh@&͵(Py0qmK'fB{9>5#BF? b K6{z>&yFY?o?uk]ޗ M睞\.;j=Rv1W VV6,֭(`@FZpg1ۑ7b)؇{8kd6L7nLrSPGeZBtx 1N@mF(n=~8avk^ JHx&mгhR5 Rv aI0t54DgHVǓq]RB"t;31kN\wT\>%"1'MA@sD1EgPtܰSZպ1y0?j>Nx&I\~ ĪvŠ}'Bp}tV%Muܐ~u2ktcm2Akn΍ ^|m DPmDP$3v;Έq;l&ϥyY]U ƴ1,;/nvj{3 !A,4̊X#18,\B8mGN7lmx9h+@kkkڪBC 4R__H(O0kZ4 *X2UJ9{X mmlz)_*dk&."q4著UhcuQL`K;F2C8BF8+56m̷{#BSul;2=kLBfa߱6Mh3͍A!p߭'E=tL4+E(BiXser4+2&gٽ&.9g!Jcx'rB%AxB3ֶjS-~#'4yu#v9 ͪJc)"sZCUR 4`wc Ƞ-;(<\r_@^BV SÅMV)j-=d$Sb^w(L2>?)jk XB͚Vjq<6b. lmV`/=6/B &&nV"=ʎL[3+?^7 NX,>` ]3(M>舍(fi#xKDaw[[Eض RaWH 4gtUz[bu8c6 em6/\r;`;̧'VS}^e~0YhJ;-ݡp]Y[iAц&e,*?xkkS, Mhm_|SAۄupc&1Z>G,$%h(%&x0mlt9bwy0Ñd!H :FЄc{;1tՖcCD{cuDl0>E+Cd8:SnKc_akpZU4%mz!c-֙) Sã혬=t%Hu m&N D@dk+,?_mfքHS҆|hWWhpF+X#K'mUj(d\e;3ge_&lxu .ı%ȊJx;C59ޟkV}fă~C.sKii;J禬._X{mzbDAhG հҴFcdzCC SalDB;* "߯9[7dÊ`*AO`m9tbZd(4H & kQ}k!1䱁ZNi nzJU &ڪ0o!q%rC3d6]si}N45/BI%:'pX0XTͬ)00V<LE%7q8,k)4plT9H`[{>o{p1 R0x|Ok58rdz)f!08PsOTH#)JIe|CԎ @`]vdjLZ㹸(t ~_˗6dͨ8. g,Ņ2Bs^z\O`$Ӛ1 މ8! ͺo!S!tX E_}6 ]~?Z xΪQn*m0Ep;RNϔͱc66) I#yBMj~w#< >X2vA̮ 6g_bFUucָ xa0l\6ǡW˚ZQkp̞3U2 .3҅. 9Ec ߦjjU0lNY^j;CD[b{+TT"E60?gcu+;6e{*X4ԩrZ lvBӅi˳n}az]+=5Bvsڴh|&{7pm{ 0CjzI7 6V+ӱ sp,i,P0diF'3A!b@&/@ue-f1W!nb>jxB[isbύySh́kӶlĵek]*5{uL;+3>pA1ʧ7ڂ  ] l+givΗ+`KCoWpQh˞)A6c񅎆t_ k:MTubRjޏ᧘-vݷo\ =+3haQl֮}!aчRuGwYD(= tr&ό>={stht/96Aظ=(Q6Ѱ Gڿ08qqp3m?YNb9K+w!{c6Y~5o3>y*~lNLmo:6SDq3(FϚ$% Řj b٬OMڋ/a {k{~#4ai}MK 00m0;h0E]Nf.ThsYDӕ' co ǘqBO.# w3p  Ph6SHSx0AF eey.m/9P\mb.:4'Lpr|K4:777CTWe7;PBhYELU1^ۆq@RpMfbŠj90d o[#1C Ul6)JxGhN!]ۍ1o!A\e~ aQ ,B $l<0+q tsQhx'#GF_.K| 7a%VQ²'{HBlxqQ1}6`ԃm06ӃVTY4+SY:v[@,Hk{_ qzV!2nBQRk'dy pyԄ\dV0dP#2O=Iئe3a!*O07"JOB8e7mosFh)s 1M$v 7^_VQS#tv!"f KDJL I1V)ז܇gu%۠:VC]B{Xǁu$2QEVh{!n聓\F̗ LlCZInn3| s&`jJ(8zۆ?l4F3ð,DI,b+#S`![hNYJquf-V*la\X fC7b61F좭azR><)OӾ}Lm?NUi;1!<ڳZ%TMv20Q6Cɛ,u=Bs i c1u}.D ofj׹k^ XHek&b>sկvVmOJ_IDAT~:?xΥK㍟+G og=6R\= lf1.pFwqgS[CeN emu1?m XC-AYLm7,p^ q_mh8wDV0>;5ϟ;3g0Co{?C=ld믭gˎj[}؅!Q#":kO, i4]k9ok5Tu!B'0LV<{ڼ&2s^J= q,o >5K9~<9~g~fp&];IھK vduW.؊@ct1H:ZȄ)4L HT>JA[26@9?dSS"t^Vc$D 3Βpsfup` C eϾus^~7_`nnvzhC̢eKNfhYRp8 &kcw[-Ue!ʽ6ͦK@e#;C2YnY3"a4 ѐ *~XL477,- _7.?ook6:sB`z7 Ui+ἾDŽ,Zu2*Y} #69 Ha؜Sd10CqT|(he ƾIcUav#N ިV_s`#~4%v>K"\>ov]f$o&!4;M\xh3 vsOBͪj[a% cMb{ AfRkړJL,XI'jdSPPFp_W%R34 4+k ȇJ)BLJNh ': +lx^$@[蚅odN}'* LqPnl>Ѕ R}!7{-iCx`'bVxƏ.- ^_;}C{ ;!ۜo:'pAR@+C fJkDt61 Ѱ8^(JehNg:Дj7Z1 B# W_?@cd 4WCaɈE7*m 5箯M(/4|ˣc{Y(T%t{/obZXU͖TLUF2^wW5nB-dЫ-jePdo86ןkH`yc8iolFd Ϻ6!2VK 9N,&k0.F;s6w:rdbo(H`}% 90T7+ fʟKhnVX2 +B5gc%VM ` sxFU 5,7uMHphp-axPx.q荧⸝gwlyzI9jɟ0+wXn7+bf@iBq[M|:Bƈ6ۂF0yELMa#K^LsGM?Ei7ts=Ceb`uBp/XʱBP`L@,?=<~>7Td??*bO!IjBA*v97xOB5/,)[n0Ԫ)sO1ڄa0 ƪ: g,ǎ-ԎL#߿q_s~>!=fl"1mU۠R23| #A֠zZ,;V揋;WnpnIENDB`(0` % q{{zzzzzz{{||}}f q}}||||}}}}~~f}}||||}}}}\r~~NKD(Dj/cdo#5U =z\4L 6M\`>|%o+M Nl5}Iq5b*BB_  %,{.[{4rl'k  7nm*Ko$ 7vI/$3BlGT;Lgn(Qo 8oy/s%?$=+$6V;/#25o@.M,` JQ<#b '&U4x,QT4w+QQ<#b &'?.M+_ Jy/r$?#<+#5U;/#25nlGT;Kfn(Qo 8pvI/#3Bm*Jn# 7l'k  7n5b*AA^  %,z-[z4rM[`={$n+L Mk4{Iq\4L 6o"4U =zC(Ci/bd~~MK}}\r}}||||}}t}}||||}}}}~~juzzyyyyyyzz}}~~m ( @ H||zz{{||}}B~~}}~~~~cq3jn3e 2b}r{PLf G_R,Vu.@  BT)Rm|L%3'4}3F 6g3s#On&IgG5 -UfJ.  3XEiy}6}-E',}6|,E',J-  2WEiy3r#Nm&HfG5 -Uf}2F 5gL$3'4,Vu-@  AS)Ql|rzOLe G_R3e 2a}p2im~~c~~}}~~J||zz{{||}}E(  @}}~~yS!=M:I $Yem8ky*@JR D[aQ D[aem8ky)@J:I $YS!=My}}~~}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}fractalnow-0.8.2/lib/include/fractal_cache.h000664 001750 001750 00000021511 13175115345 020713 0ustar00mpegmpeg000000 000000 /* * fractal_cache.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal_cache.h * \brief Main header file related to fractal cache. */ #ifndef __FRACTAL_CACHE_H__ #define __FRACTAL_CACHE_H__ #include "color.h" #include "float_precision.h" #include "fractal_rendering_parameters.h" #include "image.h" #include "thread.h" #include #include #ifdef __cplusplus extern "C" { #endif /** * \def DEFAULT_FRACTAL_CACHE_SIZE * \brief Default fractal cache size (number of entries). */ #define DEFAULT_FRACTAL_CACHE_SIZE (uint_least64_t)(300000) /** * \def DEFAULT_CACHE_WEIGHT_THRESHOLD * \brief Default threshold for ArrayValue validity. * * \see isArrayValueValid */ #define DEFAULT_CACHE_WEIGHT_THRESHOLD (FLOATTYPE(FP_LDOUBLE))(0.) /** * \struct CacheEntry * \brief Cache entry. */ /** * \typedef CacheEntry * \brief Convenient typedef for struct CacheEntry. */ typedef struct CacheEntry { FloatPrecision floatPrecision; /*!< Float precision for x and y values.*/ MultiFloat x; /*!< x coordinate.*/ MultiFloat y; /*!< y coordinate.*/ double value; /*!< Value at point (x,y).*/ } CacheEntry; /** * \struct ArrayValue * \brief Type of cache array elements. */ /** * \typedef ArrayValue * \brief Convenient typedef for struct ArrayValue. */ typedef struct ArrayValue { uint_fast32_t state; /*!< Value state, used to test validity.*/ double r; /*!< Sum of weighted red values.*/ double g; /*!< Sum of weighted green values.*/ double b; /*!< Sum of weighted blue values.*/ double totalWeight; /*!< Total weight.*/ } ArrayValue; struct Fractal; /** * \struct FractalCache * \brief Fractal cache for fractal drawing. * * When using cache to create an image preview * all entries are placed at the correct position * in the array (resized to image size), and the * image is produced from this array. */ /** * \typedef FractalCache * \brief Convenient type for struct FractalCache. */ typedef struct FractalCache { int firstUse; /*!< Indicates whether or not cache has already been used.*/ struct Fractal *fractal; /*!< Current fractal cached.*/ RenderingParameters *render; /*!< Current rendering parameters cached.*/ uint_fast32_t currentState; /*!< Current cache state (used for testing array values validity.*/ uint_least64_t nbInitialized; /*!< Number of entries already initialized (if cache is not full yet).*/ uint_least64_t size; /*!< Cache size (total number of entries it can contain).*/ CacheEntry *entry; /*!< Array of entries.*/ uint_least64_t currentIndex; /*!< Current entry index.*/ uint_fast32_t arrayWidth; /*!< Array width.*/ uint_fast32_t arrayHeight; /*!< Array height.*/ ArrayValue **array; /*!< Cache array.*/ pthread_spinlock_t arrayMutex; /*!< Mutex for cache array.*/ pthread_spinlock_t entryMutex; /*!< Mutex for cache entries.*/ } FractalCache; /** * \fn int CreateFractalCache(FractalCache *cache, uint_least64_t size) * \brief Create fractal cache. * * In case of failure, cache is initialised with size = 0. * * \param cache Pointer to cache structure to initialize. * \param size Cache size (maximum number of entries). * \return 0 in case of success, 1 otherwise. */ int CreateFractalCache(FractalCache *cache, uint_least64_t size); /** * \fn int ResizeCacheThreadSafe(FractalCache *cache, uint_least64_t size) * \brief Resize cache (thread-safe). * * In case of failure, cache is left unchanged. * * \param cache Pointer to cache to resize. * \param size New cache size (maximum number of entries). * \return 0 in case of success, 1 otherwise. */ int ResizeCacheThreadSafe(FractalCache *cache, uint_least64_t size); /** * \fn void AddToCache(FractalCache *cache, CacheEntry entry) * \brief Add entry to cache. * * This function is not thread-safe (like most of the * functions in this library).\n * \see AddToCacheThreadSafe * * \param cache Pointer to cache. * \param entry Cache entry */ void AddToCache(FractalCache *cache, CacheEntry entry); /** * \fn void AddToCacheThreadSafe(FractalCache *cache, CacheEntry) * \brief Add entry to cache (thread-safe). * * This function is thread-safe (unlike most of the * functions in this library).\n * \see AddToCache * * \param cache Pointer to cache. * \param entry Cache entry. */ void AddToCacheThreadSafe(FractalCache *cache, CacheEntry entry); /** * \fn ArrayValue GetArrayValue(FractalCache *cache, uint_fast32_t x, uint_fast32_t y) * \brief Get value from cache array. * * The function does not check that (x,y) is within * cache array range (hence unspecified behaviour * otherwise). * * \param cache Pointer to cache structure. * \param x X coordinate. * \param y Y coordinate. * \return Array value at point (x,y). */ ArrayValue GetArrayValue(FractalCache *cache, uint_fast32_t x, uint_fast32_t y); /** * \fn int isArrayValueValid(ArrayValue aVal, FractalCache *cache) * \brief Check whether an array value is valid or not. * * If an array value is valid, it can be used to create * a preview of a fractal image.\n * An array value is valid if: * -its state is equal to cache current state * -its total weight is stricly greater than * DEFAULT_CACHE_WEIGHT_THRESHOLD * This "cache and value state" is a trick used to avoid * having to clear cache array before creating an * image preview. * * \param aVal Array value. * \param cache Pointer to cache structure. * \return 1 of value is valid, 0 otherwise. */ int isArrayValueValid(ArrayValue aVal, FractalCache *cache); /** * \fn Color GetColorFromAVal(ArrayValue aVal, const RenderingParameters *render) * \brief Get color from array value. * * Array value *must* be valid to get color from it.\n * \see isArrayValueValid * * \param aVal Array value. * \param render Rendering parameters to render color. * \return Corresponding color. */ Color GetColorFromAVal(ArrayValue aVal, const RenderingParameters *render); /** * \fn Task *CreateFractalCachePreviewTask(Image *dst, FractalCache *cache, const struct Fractal *fractal, const RenderingParameters *render, int fillImageOnTheFly, uint_fast32_t nbThreads) * \brief Create task generating an image preview from cache. * * The task generate an image preview AND updates the * cache array.\n * When the image is not filled on the fly, image begins * to be filled AFTER cache array has been updated.\n * When the image is filled on the fly, image is filled * while cache array is being filled.\n * The "on the fly" can be used to see image being filled * as soon as possible, but can be costlier. * * \param dst Destination image. * \param cache Cache. * \param fractal Fractal. * \param render Rendering parameters. * \param fillImageOnTheFly Indicates if the image should be filled on the fly. * \param nbThreads Number of threads that action will need to be launched. * \return Corresponding newly-allocated task. */ Task *CreateFractalCachePreviewTask(Image *dst, FractalCache *cache, const struct Fractal *fractal, const RenderingParameters *render, int fillImageOnTheFly, uint_fast32_t nbThreads); /** * \fn void FractalCachePreview(Image *dst, FractalCache *cache, const struct Fractal *fractal, const RenderingParameters *render, int fillImageOnTheFly, Threads *threads) * \brief Generate fractal image preview from cache (blocking). * * \see CreateFractalCachePreviewTask * * \param dst Destination image. * \param cache Cache. * \param fractal Fractal. * \param render Rendering parameters. * \param fillImageOnTheFly Indicates if the image should be filled on the fly. * \param threads Threads to be used for task. */ void FractalCachePreview(Image *dst, FractalCache *cache, const struct Fractal *fractal, const RenderingParameters *render, int fillImageOnTheFly, Threads *threads); /** * \fn void FreeFractalCache(FractalCache *cache) * \brief Free fractal cache. * * \param cache Pointer to cache structure to be free'd. */ void FreeFractalCache(FractalCache *cache); /** * \fn void FreeCacheEntry(CacheEntry entry) * \brief Free a cache entry. * * \param entry CacheEntry structure to be freed. */ void FreeCacheEntry(CacheEntry entry); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/gui/include/hoverpoints.h000664 001750 001750 00000006725 13175125370 020563 0ustar00mpegmpeg000000 000000 /**************************************************************************** ** ** This file is based on some files of the demonstration applications of the ** Qt Toolkit. ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Modified to be used as a part of FractalNow: ** Copyright (c) 2012 Marc Pegon ** ** This file can be distributed and/or modified under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation. ** You should have received a copy of the GNU General Public License ** along with this file; if not, write to the Free Software Foundation, Inc., ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ** ****************************************************************************/ #ifndef __HOVERPOINTS_H__ #define __HOVERPOINTS_H__ #include #include #include QT_FORWARD_DECLARE_CLASS(QBypassWidget) class HoverPoints : public QObject { Q_OBJECT public: enum PointShape { CircleShape, RectangleShape }; enum LockType { LockToLeft = 0x01, LockToRight = 0x02, LockToTop = 0x04, LockToBottom = 0x08 }; enum SortType { NoSort, XSort, YSort }; enum ConnectionType { NoConnection, LineConnection, CurveConnection }; HoverPoints(QWidget *widget, PointShape shape); bool eventFilter(QObject *object, QEvent *event); void paintPoints(); inline QRectF boundingRect() const; void setBoundingRect(const QRectF &boundingRect) { m_bounds = boundingRect; } QPolygonF points() const { return m_points; } void setPoints(const QPolygonF &points); QSizeF pointSize() const { return m_pointSize; } void setPointSize(const QSizeF &size) { m_pointSize = size; } SortType sortType() const { return m_sortType; } void setSortType(SortType sortType) { m_sortType = sortType; } ConnectionType connectionType() const { return m_connectionType; } void setConnectionType(ConnectionType connectionType) { m_connectionType = connectionType; } void setConnectionPen(const QPen &pen) { m_connectionPen = pen; } void setShapePen(const QPen &pen) { m_pointPen = pen; } void setShapeBrush(const QBrush &brush) { m_pointBrush = brush; } void setPointLock(int pos, LockType lock) { m_locks[pos] = lock; } void setEditable(bool editable) { m_editable = editable; } bool editable() const { return m_editable; } public slots: void setEnabled(bool enabled); void setDisabled(bool disabled) { setEnabled(!disabled); } signals: void pointsChanged(const QPolygonF &points); public: void firePointChange(); private: inline QRectF pointBoundingRect(int i) const; void movePoint(int i, const QPointF &newPos, bool emitChange = true); QWidget *m_widget; QPolygonF m_points; QRectF m_bounds; PointShape m_shape; SortType m_sortType; ConnectionType m_connectionType; QVector m_locks; QSizeF m_pointSize; int m_currentIndex; bool m_editable; bool m_enabled; QHash m_fingerPointMapping; QPen m_pointPen; QBrush m_pointBrush; QPen m_connectionPen; }; inline QRectF HoverPoints::pointBoundingRect(int i) const { QPointF p = m_points.at(i); qreal w = m_pointSize.width(); qreal h = m_pointSize.height(); qreal x = p.x() - w / 2; qreal y = p.y() - h / 2; return QRectF(x, y, w, h); } inline QRectF HoverPoints::boundingRect() const { if (m_bounds.isEmpty()) { return m_widget->rect(); } else { return m_bounds; } } #endif fractalnow-0.8.2/examples/rendering_files/render01d.render000664 001750 001750 00000000135 13175112471 023550 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING TRIANGLEINEQUALITY SPLINE LOG 6.3 0 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/examples/rendering_files/render04c.render000664 001750 001750 00000000122 13175112471 023546 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING STRIPE 1 LINEAR CUBE 1 0 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/examples/rendering_files/render03b.render000664 001750 001750 00000000130 13175112471 023543 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING CURVATURE NONE CUBE 7.5E-2 0.5 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/examples/000775 001750 001750 00000000000 13175112471 015425 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/gui/src/main.cpp000664 001750 001750 00000002316 13175125537 016623 0ustar00mpegmpeg000000 000000 /* * main.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "main.h" #include "main_window.h" #include int main(int argc, char *argv[]) { QApplication::setApplicationName("QFractalNow"); QApplication::setOrganizationName("fractalnow"); QApplication::setApplicationVersion(QString(FractalNow_VersionNumber())); QApplication app(argc, argv); MainWindow mainWindow(argc, argv); mainWindow.show(); return app.exec(); } fractalnow-0.8.2/lib/include/float_precision.h000664 001750 001750 00000123174 13175115345 021344 0ustar00mpegmpeg000000 000000 /* * float_precision.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file float_precision.h * \brief Header file related to floating point types for different precision. * * \author Marc Pegon */ #ifndef __FLOAT_PRECISION_H__ #define __FLOAT_PRECISION_H__ #include "complex_wrapper.h" #include #include #include #ifdef _ENABLE_MP_FLOATS #include #include #include #endif #ifdef __cplusplus extern "C" { #endif /** * \enum e_FloatPrecision * \brief Supported float precisions (types). */ /** * \typedef FloatPrecision * \brief Convenient typedef for enum e_FloatPrecision. */ typedef enum e_FloatPrecision { FP_SINGLE = 0, /*!< Single precision (float).*/ FP_DOUBLE, /*!< Double precision (double).*/ #ifdef _ENABLE_LDOUBLE_FLOATS FP_LDOUBLE, #endif /*!< Extended precision (long double).*/ #ifdef _ENABLE_MP_FLOATS FP_MP #endif /* Multiple precision (mpfr_t and mpc_t).*/ } FloatPrecision; #define FLOATTYPE_FP_SINGLE float #define COMPLEX_FLOATTYPE_FP_SINGLE Complex_f #define FLOATTYPE_FP_DOUBLE double #define COMPLEX_FLOATTYPE_FP_DOUBLE Complex_ #define FLOATTYPE_FP_LDOUBLE long double #define COMPLEX_FLOATTYPE_FP_LDOUBLE Complex_l #define FLOATTYPE_FP_MP mpfr_t #define COMPLEX_FLOATTYPE_FP_MP mpc_t #define FLOATTYPE(fprec) FLOATTYPE_##fprec #define COMPLEX_FLOATTYPE(fprec) COMPLEX_FLOATTYPE_##fprec /** * \union MultiFloat * \brief Union for different types of float. */ /** * \typedef MultiFloat * \brief Convenient typedef for union MultiFloat. */ typedef union MultiFloat { FLOATTYPE(FP_SINGLE) val_FP_SINGLE; /*!< float type value.*/ FLOATTYPE(FP_DOUBLE) val_FP_DOUBLE; #ifdef _ENABLE_LDOUBLE_FLOATS /*!< double type value.*/ FLOATTYPE(FP_LDOUBLE) val_FP_LDOUBLE; #endif #ifdef _ENABLE_MP_FLOATS /*!< long double type value.*/ FLOATTYPE(FP_MP) val_FP_MP; /*!< mpfr_t type value.*/ #endif } MultiFloat; /** * \var nbFloatPrecisions * \brief Number of diffenret float precisions. */ extern const uint_fast32_t nbFloatPrecisions; /** * \var floatPrecisionStr * \brief Strings of float precisions. */ extern const char *floatPrecisionStr[]; /** * \var floatPrecisionDescStr * \brief More descriptive strings for float precisions. */ extern const char *floatPrecisionDescStr[]; /** * \fn int GetFloatPrecision(FloatPrecision *floatPrecision, const char *str) * \brief Get float precision from string. * * Function is case insensitive. * Possible strings are : * - "single" for FP_SINGLE * - "double" for FP_DOUBLE * - "ldouble" for FP_LDOUBLE * - "mp" for FP_MP if MP floats are enabled * * \param floatPrecision Float precision destination. * \param str String specifying float precision. * \return 0 in case of success, 1 in case of failure. */ int GetFloatPrecision(FloatPrecision *floatPrecision, const char *str); #ifdef _ENABLE_MP_FLOATS #define DEFAULT_MP_PRECISION (int64_t)(128) extern int64_t fractalnow_mp_precision; /** * \fn int64_t GetMinMPFloatPrecision() * \brief Get minimum precision of MP floats. * * \return Minimum precision of Multiple Precision floats. */ int64_t GetMinMPFloatPrecision(); /** * \fn int64_t GetMaxMPFloatPrecision() * \brief Get maximum precision of MP floats. * * \return Maximum precision of Multiple Precision floats. */ int64_t GetMaxMPFloatPrecision(); /** * \fn int64_t GetMPFloatPrecision() * \brief Get current precision of MP floats. * * \return Current precision of Multiple Precision floats. */ int64_t GetMPFloatPrecision(); /** * \fn void SetMPFloatPrecision(int64_t precision); * \brief Set precision of MP floats. * * Does nothing if precision is not between minimum and maximum precision. * * \param precision New Multiple Float precision. */ void SetMPFloatPrecision(int64_t precision); #endif /************************FP_SINGLE************************/ #define init_FP_SINGLE(x) (void)NULL #define clear_FP_SINGLE(x) (void)NULL #define cinit_FP_SINGLE(x) (void)NULL #define cclear_FP_SINGLE(x) (void)NULL #define assign_FP_SINGLE(dst,src) dst=src #define cassign_FP_SINGLE(dst,src) dst=src #define fromMPFR_FP_SINGLE(dst,src) dst=mpfr_get_flt(src,MPFR_RNDN) #define fromLDouble_FP_SINGLE(dst,src) dst=(FLOATTYPE_FP_SINGLE)src #define fromDouble_FP_SINGLE(dst,src) dst=(FLOATTYPE_FP_SINGLE)src #define fromUi_FP_SINGLE(dst,src) dst=(FLOATTYPE_FP_SINGLE)src #define fromSi_FP_SINGLE(dst,src) dst=(FLOATTYPE_FP_SINGLE)src #define toDouble_FP_SINGLE(src) (long double)src #define cfromMPC_FP_SINGLE(dst,src) dst=cbuild_f(mpfr_get_flt(mpc_realref(src),MPFR_RNDN),mpfr_get_flt(mpc_imagref(src),MPFR_RNDN)) #define cfromCLDouble_FP_SINGLE(dst,src) dst=cbuild_f((float)creal_l(src),(float)cimag_l(src)) #define cfromUi_FP_SINGLE(dst,src) dst=cbuild_f((float)src, 0) #define cfromSi_FP_SINGLE(dst,src) dst=cbuild_f((float)src, 0) #define cfromReIm_FP_SINGLE(dst,re,im) dst=cbuild_f(re,im) #define cfromCDouble_FP_SINGLE(dst,src) dst=cbuild_f((float)creal_(src),(float)cimag_(src)) #define ctoCDouble_FP_SINGLE(src) cbuild_((double)creal_f(src), (double)cimag_f(src)) #define cmp_FP_SINGLE(x,y) ((xy)?1:0)) #define cmp_ui_FP_SINGLE(x,y) ((xy)?1:0)) #define cmp_si_FP_SINGLE(x,y) ((xy)?1:0)) #define eq_ui_FP_SINGLE(x,y) (x==y) #define eq_si_FP_SINGLE(x,y) (x==y) #define ceq_si_FP_SINGLE(x,y) ceq_f(x, cbuild_f(y, 0)) #define ceq_FP_SINGLE(x,y) ceq_f(x,y) #define cisinteger_FP_SINGLE(x) cisinteger_f(x) #define add_FP_SINGLE(res,x,y) res=((x)+(y)) #define sub_FP_SINGLE(res,x,y) res=((x)-(y)) #define mul_FP_SINGLE(res,x,y) res=((x)*(y)) #define div_FP_SINGLE(res,x,y) res=((x)/(y)) #define add_d_FP_SINGLE(res,x,y) res=((x)+(y)) #define sub_d_FP_SINGLE(res,x,y) res=((x)-(y)) #define mul_d_FP_SINGLE(res,x,y) res=((x)*(y)) #define div_d_FP_SINGLE(res,x,y) res=((x)/(y)) #define add_ui_FP_SINGLE(res,x,y) res=((x)+(y)) #define sub_ui_FP_SINGLE(res,x,y) res=((x)-(y)) #define mul_ui_FP_SINGLE(res,x,y) res=((x)*(y)) #define div_ui_FP_SINGLE(res,x,y) res=((x)/(y)) #define add_si_FP_SINGLE(res,x,y) res=((x)+(y)) #define sub_si_FP_SINGLE(res,x,y) res=((x)-(y)) #define mul_si_FP_SINGLE(res,x,y) res=((x)*(y)) #define div_si_FP_SINGLE(res,x,y) res=((x)/(y)) #define cadd_FP_SINGLE(res,x,y) res=cadd_f(x,y) #define csub_FP_SINGLE(res,x,y) res=csub_f(x,y) #define cmul_FP_SINGLE(res,x,y) res=cmul_f(x,y) #define cdiv_FP_SINGLE(res,x,y) res=cdiv_f(x,y) #define sqr_FP_SINGLE(res,x) res=((x)*(x)) #define csqr_FP_SINGLE(res,x) res=csqr_f(x) #define fabs_FP_SINGLE(res,x) res=fabsf(x) #define cabs_FP_SINGLE(res,z) res=cabs_f(z) #define cnorm_FP_SINGLE(res,z) res=cnorm_f(z) #define creal_FP_SINGLE(res,z) res=creal_f(z) #define cimag_FP_SINGLE(res,z) res=cimag_f(z) #define carg_FP_SINGLE(res,z) res=carg_f(z) #define cpow_FP_SINGLE(res,z,y) res=cpow_f(z,y) #define cipow_FP_SINGLE(res,z,y) res=cipow_f(z,y) #define conj_FP_SINGLE(res,z) res=conj_f(z) #define round_FP_SINGLE(res,x) res=roundf(x) #define floor_FP_SINGLE(res,x) res=floorf(x) #define pow_FP_SINGLE(res,x,y) res=powf(x,y) #define fmax_FP_SINGLE(res,x,y) res=fmaxf(x,y) #define modf_FP_SINGLE(ires,fres,x) fres=modff(x,&ires) #define exp_FP_SINGLE(res,x) res=expf(x) #define log_FP_SINGLE(res,x) res=logf(x) #define sqrt_FP_SINGLE(res,x) res=sqrtf(x) #define sin_FP_SINGLE(res,x) res=sinf(x) #define cos_FP_SINGLE(res,x) res=cosf(x) #define tan_FP_SINGLE(res,x) res=tanf(x) /*********************************************************/ /************************FP_DOUBLE************************/ #define init_FP_DOUBLE(x) (void)NULL #define clear_FP_DOUBLE(x) (void)NULL #define cinit_FP_DOUBLE(x) (void)NULL #define cclear_FP_DOUBLE(x) (void)NULL #define assign_FP_DOUBLE(dst,src) dst=src #define cassign_FP_DOUBLE(dst,src) dst=src #define fromMPFR_FP_DOUBLE(dst,src) dst=mpfr_get_d(src,MPFR_RNDN) #define fromLDouble_FP_DOUBLE(dst,src) dst=(FLOATTYPE_FP_DOUBLE)src #define fromDouble_FP_DOUBLE(dst,src) dst=(FLOATTYPE_FP_DOUBLE)src #define fromUi_FP_DOUBLE(dst,src) dst=(FLOATTYPE_FP_DOUBLE)src #define fromSi_FP_DOUBLE(dst,src) dst=(FLOATTYPE_FP_DOUBLE)src #define toDouble_FP_DOUBLE(src) (long double)src #define cfromMPC_FP_DOUBLE(dst,src) dst=cbuild_(mpfr_get_d(mpc_realref(src),MPFR_RNDN),mpfr_get_d(mpc_imagref(src),MPFR_RNDN)) #define cfromCLDouble_FP_DOUBLE(dst,src) dst=cbuild_((double)creal_l(src),(double)cimag_l(src)) #define cfromUi_FP_DOUBLE(dst,src) dst=cbuild_((double)src, 0) #define cfromSi_FP_DOUBLE(dst,src) dst=cbuild_((double)src, 0) #define cfromReIm_FP_DOUBLE(dst,re,im) dst=cbuild_(re,im) #define cfromCDouble_FP_DOUBLE(dst,src) dst=src #define ctoCDouble_FP_DOUBLE(src) src #define cmp_FP_DOUBLE(x,y) ((xy)?1:0)) #define cmp_ui_FP_DOUBLE(x,y) ((xy)?1:0)) #define cmp_si_FP_DOUBLE(x,y) ((xy)?1:0)) #define eq_ui_FP_DOUBLE(x,y) (x==y) #define eq_si_FP_DOUBLE(x,y) (x==y) #define ceq_si_FP_DOUBLE(x,y) ceq_(x, cbuild_(y, 0)) #define ceq_FP_DOUBLE(x,y) ceq_(x, y) #define cisinteger_FP_DOUBLE(x) cisinteger_(x) #define add_FP_DOUBLE(res,x,y) res=((x)+(y)) #define sub_FP_DOUBLE(res,x,y) res=((x)-(y)) #define mul_FP_DOUBLE(res,x,y) res=((x)*(y)) #define div_FP_DOUBLE(res,x,y) res=((x)/(y)) #define add_d_FP_DOUBLE(res,x,y) res=((x)+(y)) #define sub_d_FP_DOUBLE(res,x,y) res=((x)-(y)) #define mul_d_FP_DOUBLE(res,x,y) res=((x)*(y)) #define div_d_FP_DOUBLE(res,x,y) res=((x)/(y)) #define add_ui_FP_DOUBLE(res,x,y) res=((x)+(y)) #define sub_ui_FP_DOUBLE(res,x,y) res=((x)-(y)) #define mul_ui_FP_DOUBLE(res,x,y) res=((x)*(y)) #define div_ui_FP_DOUBLE(res,x,y) res=((x)/(y)) #define add_si_FP_DOUBLE(res,x,y) res=((x)+(y)) #define sub_si_FP_DOUBLE(res,x,y) res=((x)-(y)) #define mul_si_FP_DOUBLE(res,x,y) res=((x)*(y)) #define div_si_FP_DOUBLE(res,x,y) res=((x)/(y)) #define cadd_FP_DOUBLE(res,x,y) res=cadd_(x,y) #define csub_FP_DOUBLE(res,x,y) res=csub_(x,y) #define cmul_FP_DOUBLE(res,x,y) res=cmul_(x,y) #define cdiv_FP_DOUBLE(res,x,y) res=cdiv_(x,y) #define sqr_FP_DOUBLE(res,x) res=((x)*(x)) #define csqr_FP_DOUBLE(res,x) res=csqr_(x) #define fabs_FP_DOUBLE(res,x) res=fabs(x) #define cabs_FP_DOUBLE(res,z) res=cabs_(z) #define cnorm_FP_DOUBLE(res,z) res=cnorm_(z) #define creal_FP_DOUBLE(res,z) res=creal_(z) #define cimag_FP_DOUBLE(res,z) res=cimag_(z) #define carg_FP_DOUBLE(res,z) res=carg_(z) #define cpow_FP_DOUBLE(res,z,y) res=cpow_(z,y) #define cipow_FP_DOUBLE(res,z,y) res=cipow_(z,y) #define conj_FP_DOUBLE(res,z) res=conj_(z) #define round_FP_DOUBLE(res,x) res=round(x) #define floor_FP_DOUBLE(res,x) res=floor(x) #define pow_FP_DOUBLE(res,x,y) res=pow(x,y) #define fmax_FP_DOUBLE(res,x,y) res=fmax(x,y) #define modf_FP_DOUBLE(ires,fres,x) fres=modf(x,&ires) #define exp_FP_DOUBLE(res,x) res=exp(x) #define log_FP_DOUBLE(res,x) res=log(x) #define sqrt_FP_DOUBLE(res,x) res=sqrt(x) #define sin_FP_DOUBLE(res,x) res=sin(x) #define cos_FP_DOUBLE(res,x) res=cos(x) #define tan_FP_DOUBLE(res,x) res=tan(x) /*********************************************************/ /************************FP_LDOUBLE***********************/ #define init_FP_LDOUBLE(x) (void)NULL #define clear_FP_LDOUBLE(x) (void)NULL #define cinit_FP_LDOUBLE(x) (void)NULL #define cclear_FP_LDOUBLE(x) (void)NULL #define assign_FP_LDOUBLE(dst,src) dst=src #define cassign_FP_LDOUBLE(dst,src) dst=src #define fromMPFR_FP_LDOUBLE(dst,src) dst=mpfr_get_ld(src,MPFR_RNDN) #define fromLDouble_FP_LDOUBLE(dst,src) dst=(FLOATTYPE_FP_LDOUBLE)src #define fromDouble_FP_LDOUBLE(dst,src) dst=(FLOATTYPE_FP_LDOUBLE)src #define fromUi_FP_LDOUBLE(dst,src) dst=(FLOATTYPE_FP_LDOUBLE)src #define fromSi_FP_LDOUBLE(dst,src) dst=(FLOATTYPE_FP_LDOUBLE)src #define toDouble_FP_LDOUBLE(src) (long double)src #define cfromMPC_FP_LDOUBLE(dst,src) dst=cbuild_l(mpfr_get_ld(mpc_realref(src),MPFR_RNDN),mpfr_get_ld(mpc_imagref(src),MPFR_RNDN)) #define cfromCLDouble_FP_LDOUBLE(dst,src) dst=src #define cfromUi_FP_LDOUBLE(dst,src) dst=cbuild_l((long double)src, 0) #define cfromSi_FP_LDOUBLE(dst,src) dst=cbuild_l((long double)src, 0) #define cfromReIm_FP_LDOUBLE(dst,re,im) dst=cbuild_l(re, im) #define cfromCDouble_FP_LDOUBLE(dst,src) dst=cbuild_l((double)creal_(src),(double)cimag_(src)) #define ctoCDouble_FP_LDOUBLE(src) cbuild_((double)creal_l(src),(double)cimag_l(src)) #define cmp_FP_LDOUBLE(x,y) ((xy)?1:0)) #define cmp_ui_FP_LDOUBLE(x,y) ((xy)?1:0)) #define cmp_si_FP_LDOUBLE(x,y) ((xy)?1:0)) #define ccmp_si_FP_LDOUBLE(x,y) ((xy)?1:0)) #define eq_ui_FP_LDOUBLE(x,y) (x==y) #define eq_si_FP_LDOUBLE(x,y) (x==y) #define ceq_si_FP_LDOUBLE(x,y) ceq_l(x, cbuild_l(y, 0)) #define ceq_FP_LDOUBLE(x,y) ceq_l(x,y) #define cisinteger_FP_LDOUBLE(x) cisinteger_l(x) #define add_FP_LDOUBLE(res,x,y) res=((x)+(y)) #define sub_FP_LDOUBLE(res,x,y) res=((x)-(y)) #define mul_FP_LDOUBLE(res,x,y) res=((x)*(y)) #define div_FP_LDOUBLE(res,x,y) res=((x)/(y)) #define add_d_FP_LDOUBLE(res,x,y) res=((x)+(y)) #define sub_d_FP_LDOUBLE(res,x,y) res=((x)-(y)) #define mul_d_FP_LDOUBLE(res,x,y) res=((x)*(y)) #define div_d_FP_LDOUBLE(res,x,y) res=((x)/(y)) #define add_ui_FP_LDOUBLE(res,x,y) res=((x)+(y)) #define sub_ui_FP_LDOUBLE(res,x,y) res=((x)-(y)) #define mul_ui_FP_LDOUBLE(res,x,y) res=((x)*(y)) #define div_ui_FP_LDOUBLE(res,x,y) res=((x)/(y)) #define add_si_FP_LDOUBLE(res,x,y) res=((x)+(y)) #define sub_si_FP_LDOUBLE(res,x,y) res=((x)-(y)) #define mul_si_FP_LDOUBLE(res,x,y) res=((x)*(y)) #define div_si_FP_LDOUBLE(res,x,y) res=((x)/(y)) #define cadd_FP_LDOUBLE(res,x,y) res=cadd_l(x,y) #define csub_FP_LDOUBLE(res,x,y) res=csub_l(x,y) #define cmul_FP_LDOUBLE(res,x,y) res=cmul_l(x,y) #define cdiv_FP_LDOUBLE(res,x,y) res=cdiv_l(x,y) #define sqr_FP_LDOUBLE(res,x) res=((x)*(x)) #define csqr_FP_LDOUBLE(res,x) res=csqr_l(x) #define fabs_FP_LDOUBLE(res,x) res=fabsl(x) #define cabs_FP_LDOUBLE(res,z) res=cabs_l(z) #define cnorm_FP_LDOUBLE(res,z) res=cnorm_l(z) #define creal_FP_LDOUBLE(res,z) res=creal_l(z) #define cimag_FP_LDOUBLE(res,z) res=cimag_l(z) #define carg_FP_LDOUBLE(res,z) res=carg_l(z) #define cpow_FP_LDOUBLE(res,z,y) res=cpow_l(z,y) #define cipow_FP_LDOUBLE(res,z,y) res=cipow_l(z,y) #define conj_FP_LDOUBLE(res,z) res=conj_l(z) #define round_FP_LDOUBLE(res,x) res=roundl(x) #define floor_FP_LDOUBLE(res,x) res=floorl(x) #define pow_FP_LDOUBLE(res,x,y) res=powl(x,y) #define fmax_FP_LDOUBLE(res,x,y) res=fmaxl(x,y) #define modf_FP_LDOUBLE(ires,fres,x) fres=modfl(x,&ires) #define exp_FP_LDOUBLE(res,x) res=expl(x) #define log_FP_LDOUBLE(res,x) res=logl(x) #define sqrt_FP_LDOUBLE(res,x) res=sqrtl(x) #define sin_FP_LDOUBLE(res,x) res=sinl(x) #define cos_FP_LDOUBLE(res,x) res=cosl(x) #define tan_FP_LDOUBLE(res,x) res=tanl(x) /*********************************************************/ /**************************FP_MP**************************/ #define init_FP_MP(x) mpfr_init(x) #define clear_FP_MP(x) mpfr_clear(x) #define cinit_FP_MP(x) mpc_init2(x,mpfr_get_default_prec()) #define cclear_FP_MP(x) mpc_clear(x) #define assign_FP_MP(dst,src) mpfr_set(dst,src,MPFR_RNDN) #define cassign_FP_MP(dst,src) mpc_set(dst,src,MPC_RNDNN) #define fromMPFR_FP_MP(dst,src) mpfr_set(dst,src,MPFR_RNDN) #define fromLDouble_FP_MP(dst,src) mpfr_set_ld(dst,src,MPFR_RNDN) #define fromDouble_FP_MP(dst,src) mpfr_set_d(dst,src,MPFR_RNDN) #define fromUi_FP_MP(dst,src) mpfr_set_ui(dst,src,MPFR_RNDN) #define fromSi_FP_MP(dst,src) mpfr_set_si(dst,src,MPFR_RNDN) #define toDouble_FP_MP(src) mpfr_get_ld(src,MPFR_RNDN) #define cfromMPC_FP_MP(dst,src) mpc_set(dst,src,MPC_RNDNN) #define cfromCLDouble_FP_MP(dst,src) mpc_set_ld_ld(dst,creal_l(src),cimag_l(src),MPC_RNDNN) #define cfromUi_FP_MP(dst,src) mpc_set_ui(dst,src,MPC_RNDNN) #define cfromSi_FP_MP(dst,src) mpc_set_si(dst,src,MPC_RNDNN) #define cfromReIm_FP_MP(dst,re,im) mpc_set_fr_fr(dst,re,im,MPC_RNDNN) #define cfromCDouble_FP_MP(dst,src) mpc_set_d_d(dst,creal_(src),cimag_(src),MPC_RNDNN) #define ctoCDouble_FP_MP(src) cbuild_(mpfr_get_d(mpc_realref(src),MPFR_RNDN),mpfr_get_d(mpc_imagref(src),MPFR_RNDN)) #define cmp_FP_MP(x,y) mpfr_cmp(x,y) #define cmp_ui_FP_MP(x,y) mpfr_cmp_ui(x,y) #define cmp_si_FP_MP(x,y) mpfr_cmp_si(x,y) #define eq_ui_FP_MP(x,y) (mpfr_cmp_ui(x,y)==0) #define eq_si_FP_MP(x,y) (mpfr_cmp_si(x,y)==0) #define ceq_si_FP_MP(x,y) (mpc_cmp_si(x,y)==0) #define ceq_FP_MP(x,y) (mpc_cmp(x,y)==0) #define cisinteger_FP_MP(x) mpcIsInteger(x) #define add_FP_MP(res,x,y) mpfr_add(res,x,y,MPFR_RNDN) #define sub_FP_MP(res,x,y) mpfr_sub(res,x,y,MPFR_RNDN) #define mul_FP_MP(res,x,y) mpfr_mul(res,x,y,MPFR_RNDN) #define div_FP_MP(res,x,y) mpfr_div(res,x,y,MPFR_RNDN) #define add_d_FP_MP(res,x,y) mpfr_add_d(res,x,y,MPFR_RNDN) #define sub_d_FP_MP(res,x,y) mpfr_sub_d(res,x,y,MPFR_RNDN) #define mul_d_FP_MP(res,x,y) mpfr_mul_d(res,x,y,MPFR_RNDN) #define div_d_FP_MP(res,x,y) mpfr_div_d(res,x,y,MPFR_RNDN) #define add_ui_FP_MP(res,x,y) mpfr_add_ui(res,x,y,MPFR_RNDN) #define sub_ui_FP_MP(res,x,y) mpfr_sub_ui(res,x,y,MPFR_RNDN) #define mul_ui_FP_MP(res,x,y) mpfr_mul_ui(res,x,y,MPFR_RNDN) #define div_ui_FP_MP(res,x,y) mpfr_div_ui(res,x,y,MPFR_RNDN) #define add_si_FP_MP(res,x,y) mpfr_add_si(res,x,y,MPFR_RNDN) #define sub_si_FP_MP(res,x,y) mpfr_sub_si(res,x,y,MPFR_RNDN) #define mul_si_FP_MP(res,x,y) mpfr_mul_si(res,x,y,MPFR_RNDN) #define div_si_FP_MP(res,x,y) mpfr_div_si(res,x,y,MPFR_RNDN) #define cadd_FP_MP(res,x,y) mpc_add(res,x,y,MPC_RNDNN) #define csub_FP_MP(res,x,y) mpc_sub(res,x,y,MPC_RNDNN) #define cmul_FP_MP(res,x,y) mpc_mul(res,x,y,MPC_RNDNN) #define cdiv_FP_MP(res,x,y) mpc_div(res,x,y,MPC_RNDNN) #define sqr_FP_MP(res,x) mpfr_sqr(res,x,MPFR_RNDN) #define csqr_FP_MP(res,x) mpc_sqr(res,x,MPC_RNDNN) #define fabs_FP_MP(res,x) mpfr_abs(res,x,MPFR_RNDN) #define cabs_FP_MP(res,z) mpc_abs(res,z,MPFR_RNDN) #define cnorm_FP_MP(res,z) mpc_norm(res,z,MPFR_RNDN) #define creal_FP_MP(res,z) mpc_real(res,z,MPFR_RNDN) #define cimag_FP_MP(res,z) mpc_imag(res,z,MPFR_RNDN) #define carg_FP_MP(res,z) mpc_arg(res,z,MPFR_RNDN) #define cpow_FP_MP(res,z,y) mpc_pow(res,z,y,MPC_RNDNN) #define cipow_FP_MP(res,z,y) mpc_pow_si(res,z,y,MPC_RNDNN) #define conj_FP_MP(res,z) mpc_conj(res,z,MPC_RNDNN) #define round_FP_MP(res,x) mpfr_round(res,x) #define floor_FP_MP(res,x) mpfr_floor(res,x) #define pow_FP_MP(res,x,y) mpfr_pow(res,x,y,MPFR_RNDN) #define fmax_FP_MP(res,x,y) mpfr_max(res,x,y,MPFR_RNDN) #define modf_FP_MP(ires,fres,x) mpfr_modf(ires,fres,x,MPFR_RNDN) #define exp_FP_MP(res,x) mpfr_exp(res,x,MPFR_RNDN) #define log_FP_MP(res,x) mpfr_log(res,x,MPFR_RNDN) #define sqrt_FP_MP(res,x) mpfr_sqrt(res,x,MPFR_RNDN) #define sin_FP_MP(res,x) mpfr_sin(res,x,MPFR_RNDN) #define cos_FP_MP(res,x) mpfr_cos(res,x,MPFR_RNDN) #define tan_FP_MP(res,x) mpfr_tan(res,x,MPFR_RNDN) /*********************************************************/ /**************************COMMON*************************/ #define initF(fprec,x) init_##fprec(x) #define clearF(fprec,x) clear_##fprec(x) #define cinitF(fprec,x) cinit_##fprec(x) #define cclearF(fprec,x) cclear_##fprec(x) #define assignF(fprec,dst,src) assign_##fprec(dst,src) #define cassignF(fprec,dst,src) cassign_##fprec(dst,src) #define fromMPFRF(fprec,dst,src) fromMPFR_##fprec(dst,src) #define fromLDoubleF(fprec,dst,src) fromLDouble_##fprec(dst,src) #define fromDoubleF(fprec,dst,src) fromDouble_##fprec(dst,src) #define fromUiF(fprec,dst,src) fromUi_##fprec(dst,src) #define fromSiF(fprec,dst,src) fromSi_##fprec(dst,src) #define toDoubleF(fprec,src) toDouble_##fprec(src) #define cfromMPCF(fprec,dst,src) cfromMPC_##fprec(dst,src) #define cfromCLDoubleF(fprec,dst,src) cfromCLDouble_##fprec(dst,src) #define cfromUiF(fprec,dst,src) cfromUi_##fprec(dst,src) #define cfromSiF(fprec,dst,src) cfromSi_##fprec(dst,src) #define cfromReImF(fprec,dst,re,im) cfromReIm_##fprec(dst,re,im) #define cfromCDoubleF(fprec,dst,src) cfromCDouble_##fprec(dst,src) #define ctoCDoubleF(fprec,src) ctoCDouble_##fprec(src) #define cmpF(fprec,x,y) cmp_##fprec(x,y) #define cmp_uiF(fprec,x,y) cmp_ui_##fprec(x,y) #define cmp_siF(fprec,x,y) cmp_si_##fprec(x,y) #define eq_uiF(fprec,x,y) eq_ui_##fprec(x,y) #define eq_siF(fprec,x,y) eq_si_##fprec(x,y) #define ceq_siF(fprec,x,y) ceq_si_##fprec(x,y) #define ceqF(fprec,x,y) ceq_##fprec(x,y) #define cisintegerF(fprec,x) cisinteger_##fprec(x) #define addF(fprec,res,x,y) add_##fprec(res,x,y) #define subF(fprec,res,x,y) sub_##fprec(res,x,y) #define mulF(fprec,res,x,y) mul_##fprec(res,x,y) #define divF(fprec,res,x,y) div_##fprec(res,x,y) #define add_dF(fprec,res,x,y) add_d_##fprec(res,x,y) #define sub_dF(fprec,res,x,y) sub_d_##fprec(res,x,y) #define mul_dF(fprec,res,x,y) mul_d_##fprec(res,x,y) #define div_dF(fprec,res,x,y) div_d_##fprec(res,x,y) #define add_uiF(fprec,res,x,y) add_ui_##fprec(res,x,y) #define sub_uiF(fprec,res,x,y) sub_ui_##fprec(res,x,y) #define mul_uiF(fprec,res,x,y) mul_ui_##fprec(res,x,y) #define div_uiF(fprec,res,x,y) div_ui_##fprec(res,x,y) #define add_siF(fprec,res,x,y) add_si_##fprec(res,x,y) #define sub_siF(fprec,res,x,y) sub_si_##fprec(res,x,y) #define mul_siF(fprec,res,x,y) mul_si_##fprec(res,x,y) #define div_siF(fprec,res,x,y) div_si_##fprec(res,x,y) #define caddF(fprec,res,x,y) cadd_##fprec(res,x,y) #define csubF(fprec,res,x,y) csub_##fprec(res,x,y) #define cmulF(fprec,res,x,y) cmul_##fprec(res,x,y) #define cdivF(fprec,res,x,y) cdiv_##fprec(res,x,y) #define sqrF(fprec,res,x) sqr_##fprec(res,x) #define csqrF(fprec,res,x) csqr_##fprec(res,x) #define fabsF(fprec,res,x) fabs_##fprec(res,x) #define cabsF(fprec,res,z) cabs_##fprec(res,z) #define cnormF(fprec,res,z) cnorm_##fprec(res,z) #define crealF(fprec,res,z) creal_##fprec(res,z) #define cimagF(fprec,res,z) cimag_##fprec(res,z) #define cargF(fprec,res,z) carg_##fprec(res,z) #define cpowF(fprec,res,z,y) cpow_##fprec(res,z,y) #define cipowF(fprec,res,z,y) cipow_##fprec(res,z,y) #define conjF(fprec,res,z) conj_##fprec(res,z) #define roundF(fprec,res,x) round_##fprec(res,x) #define floorF(fprec,res,x) floor_##fprec(res,x) #define powF(fprec,res,x,y) pow_##fprec(res,x,y) #define fmaxF(fprec,res,x,y) fmax_##fprec(res,x,y) #define modfF(fprec,ires,fres,x) modf_##fprec(ires,fres,x) #define expF(fprec,res,x) exp_##fprec(res,x) #define logF(fprec,res,x) log_##fprec(res,x) #define sqrtF(fprec,res,x) sqrt_##fprec(res,x) #define sinF(fprec,res,x) sin_##fprec(res,x) #define cosF(fprec,res,x) cos_##fprec(res,x) #define tanF(fprec,res,x) tan_##fprec(res,x) /*********************************************************/ /***********************BIGGEST_FLOAT*********************/ #if defined(_ENABLE_MP_FLOATS) #define BiggestFloat FLOATTYPE(FP_MP) #define BiggestComplexFloat COMPLEX_FLOATTYPE(FP_MP) #define initBiggestF(x) initF(FP_MP,x) #define clearBiggestF(x) clearF(FP_MP,x) #define cinitBiggestF(x) cinitF(FP_MP,x) #define cclearBiggestF(x) cclearF(FP_MP,x) #define assignBiggestF(dst,src) assignF(FP_MP,dst,src) #define cassignBiggestF(dst,src) cassignF(FP_MP,dst,src) #define fromMPFRBiggestF(dst,src) fromMPFRF(FP_MP,dst,src) #define fromLDoubleBiggestF(dst,src) fromLDoubleF(FP_MP,dst,src) #define fromDoubleBiggestF(dst,src) fromDoubleF(FP_MP,dst,src) #define fromUiBiggestF(dst,src) fromUiF(FP_MP,dst,src) #define fromSiBiggestF(dst,src) fromSiF(FP_MP,dst,src) #define toDoubleBiggestF(src) toDoubleF(FP_MP,src) #define cfromMPCBiggestF(dst,src) cfromMPCF(FP_MP,dst,src) #define cfromCLDoubleBiggestF(dst,src) cfromCLDoubleF(FP_MP,dst,src) #define cfromUiBiggestF(dst,src) cfromUiF(FP_MP,dst,src) #define cfromSiBiggestF(dst,src) cfromSiF(FP_MP,dst,src) #define cfromReImBiggestF(dst,re,im) cfromReImF(FP_MP,dst,re,im) #define cfromCDoubleBiggestF(dst,src) cfromCDoubleF(FP_MP,dst,src) #define ctoCDoubleBiggestF(src) ctoCDoubleF(FP_MP,src) #define cmpBiggestF(x,y) cmpF(FP_MP,x,y) #define cmp_uiBiggestF(x,y) cmp_uiF(FP_MP,x,y) #define cmp_siBiggestF(x,y) cmp_siF(FP_MP,x,y) #define eq_uiBiggestF(x,y) eq_uiF(FP_MP,x,y) #define eq_siBiggestF(x,y) eq_siF(FP_MP,x,y) #define ceq_siBiggestF(x,y) ceq_siF(FP_MP,x,y) #define ceqBiggestF(x,y) ceqF(FP_MP,x,y) #define cisintegerBiggestF(x) cisintegerF(FP_MP,x) #define addBiggestF(res,x,y) addF(FP_MP,res,x,y) #define subBiggestF(res,x,y) subF(FP_MP,res,x,y) #define mulBiggestF(res,x,y) mulF(FP_MP,res,x,y) #define divBiggestF(res,x,y) divF(FP_MP,res,x,y) #define add_dBiggestF(res,x,y) add_dF(FP_MP,res,x,y) #define sub_dBiggestF(res,x,y) sub_dF(FP_MP,res,x,y) #define mul_dBiggestF(res,x,y) mul_dF(FP_MP,res,x,y) #define div_dBiggestF(res,x,y) div_dF(FP_MP,res,x,y) #define add_uiBiggestF(res,x,y) add_uiF(FP_MP,res,x,y) #define sub_uiBiggestF(res,x,y) sub_uiF(FP_MP,res,x,y) #define mul_uiBiggestF(res,x,y) mul_uiF(FP_MP,res,x,y) #define div_uiBiggestF(res,x,y) div_uiF(FP_MP,res,x,y) #define add_siBiggestF(res,x,y) add_siF(FP_MP,res,x,y) #define sub_siBiggestF(res,x,y) sub_siF(FP_MP,res,x,y) #define mul_siBiggestF(res,x,y) mul_siF(FP_MP,res,x,y) #define div_siBiggestF(res,x,y) div_siF(FP_MP,res,x,y) #define caddBiggestF(res,x,y) caddF(FP_MP,res,x,y) #define csubBiggestF(res,x,y) csubF(FP_MP,res,x,y) #define cmulBiggestF(res,x,y) cmulF(FP_MP,res,x,y) #define cdivBiggestF(res,x,y) cdivF(FP_MP,res,x,y) #define sqrBiggestF(res,x) sqrF(FP_MP,res,x) #define csqrBiggestF(res,x) csqrF(FP_MP,res,x) #define fabsBiggestF(res,x) fabsF(FP_MP,res,x) #define cabsBiggestF(res,z) cabsF(FP_MP,res,z) #define cnormBiggestF(res,z) cnormF(FP_MP,res,z) #define crealBiggestF(res,z) crealF(FP_MP,res,z) #define cimagBiggestF(res,z) cimagF(FP_MP,res,z) #define cargBiggestF(res,z) cargF(FP_MP,res,z) #define cpowBiggestF(res,z,y) cpowF(FP_MP,res,z,y) #define cipowBiggestF(res,z,y) cipowF(FP_MP,res,z,y) #define conjBiggestF(res,z) conjF(FP_MP,res,z) #define roundBiggestF(res,x) roundF(FP_MP,res,x) #define floorBiggestF(res,x) floorF(FP_MP,res,x) #define powBiggestF(res,x,y) powF(FP_MP,res,x,y) #define fmaxBiggestF(res,x,y) fmaxF(FP_MP,res,x,y) #define modfBiggestF(ires,fres,x) modfF(FP_MP,ires,fres,x) #define expBiggestF(res,x) expF(FP_MP,res,x) #define logBiggestF(res,x) logF(FP_MP,res,x) #define sqrtBiggestF(res,x) sqrtF(FP_MP,res,x) #define sinBiggestF(res,x) sinF(FP_MP,res,x) #define cosBiggestF(res,x) cosF(FP_MP,res,x) #define tanBiggestF(res,x) tanF(FP_MP,res,x) #define fromBiggestF(fprec,res,x) fromMPFRF(fprec,res,x) #define cfromBiggestF(fprec,res,x) cfromMPCF(fprec,res,x) #elif defined(_ENABLE_LDOUBLE_FLOATS) // !defined(_ENABLE_MP_FLOATS) && defined(_ENABLE_LDOUBLE_FLOATS) #define BiggestFloat FLOATTYPE(FP_LDOUBLE) #define BiggestComplexFloat COMPLEX_FLOATTYPE(FP_LDOUBLE) #define initBiggestF(x) initF(FP_LDOUBLE,x) #define clearBiggestF(x) clearF(FP_LDOUBLE,x) #define cinitBiggestF(x) cinitF(FP_LDOUBLE,x) #define cclearBiggestF(x) cclearF(FP_LDOUBLE,x) #define assignBiggestF(dst,src) assignF(FP_LDOUBLE,dst,src) #define cassignBiggestF(dst,src) cassignF(FP_LDOUBLE,dst,src) #define fromMPFRBiggestF(dst,src) fromMPFRF(FP_LDOUBLE,dst,src) #define fromLDoubleBiggestF(dst,src) fromLDoubleF(FP_LDOUBLE,dst,src) #define fromDoubleBiggestF(dst,src) fromDoubleF(FP_LDOUBLE,dst,src) #define fromUiBiggestF(dst,src) fromUiF(FP_LDOUBLE,dst,src) #define fromSiBiggestF(dst,src) fromSiF(FP_LDOUBLE,dst,src) #define toDoubleBiggestF(src) toDoubleF(FP_LDOUBLE,src) #define cfromMPCBiggestF(dst,src) cfromMPCF(FP_LDOUBLE,dst,src) #define cfromCLDoubleBiggestF(dst,src) cfromCLDoubleF(FP_LDOUBLE,dst,src) #define cfromUiBiggestF(dst,src) cfromUiF(FP_LDOUBLE,dst,src) #define cfromSiBiggestF(dst,src) cfromSiF(FP_LDOUBLE,dst,src) #define cfromReImBiggestF(dst,re,im) cfromReImF(FP_LDOUBLE,dst,re,im) #define cfromCDoubleBiggestF(dst,src) cfromCDoubleF(FP_LDOUBLE,dst,src) #define ctoCDoubleBiggestF(src) ctoCDoubleF(FP_LDOUBLE,src) #define cmpBiggestF(x,y) cmpF(FP_LDOUBLE,x,y) #define cmp_uiBiggestF(x,y) cmp_uiF(FP_LDOUBLE,x,y) #define cmp_siBiggestF(x,y) cmp_siF(FP_LDOUBLE,x,y) #define eq_uiBiggestF(x,y) eq_uiF(FP_LDOUBLE,x,y) #define eq_siBiggestF(x,y) eq_siF(FP_LDOUBLE,x,y) #define ceq_siBiggestF(x,y) ceq_siF(FP_LDOUBLE,x,y) #define ceqBiggestF(x,y) ceqF(FP_LDOUBLE,x,y) #define cisintegerBiggestF(x) cisintegerF(FP_LDOUBLE,x) #define addBiggestF(res,x,y) addF(FP_LDOUBLE,res,x,y) #define subBiggestF(res,x,y) subF(FP_LDOUBLE,res,x,y) #define mulBiggestF(res,x,y) mulF(FP_LDOUBLE,res,x,y) #define divBiggestF(res,x,y) divF(FP_LDOUBLE,res,x,y) #define add_dBiggestF(res,x,y) add_dF(FP_LDOUBLE,res,x,y) #define sub_dBiggestF(res,x,y) sub_dF(FP_LDOUBLE,res,x,y) #define mul_dBiggestF(res,x,y) mul_dF(FP_LDOUBLE,res,x,y) #define div_dBiggestF(res,x,y) div_dF(FP_LDOUBLE,res,x,y) #define add_uiBiggestF(res,x,y) add_uiF(FP_LDOUBLE,res,x,y) #define sub_uiBiggestF(res,x,y) sub_uiF(FP_LDOUBLE,res,x,y) #define mul_uiBiggestF(res,x,y) mul_uiF(FP_LDOUBLE,res,x,y) #define div_uiBiggestF(res,x,y) div_uiF(FP_LDOUBLE,res,x,y) #define add_siBiggestF(res,x,y) add_siF(FP_LDOUBLE,res,x,y) #define sub_siBiggestF(res,x,y) sub_siF(FP_LDOUBLE,res,x,y) #define mul_siBiggestF(res,x,y) mul_siF(FP_LDOUBLE,res,x,y) #define div_siBiggestF(res,x,y) div_siF(FP_LDOUBLE,res,x,y) #define caddBiggestF(res,x,y) caddF(FP_LDOUBLE,res,x,y) #define csubBiggestF(res,x,y) csubF(FP_LDOUBLE,res,x,y) #define cmulBiggestF(res,x,y) cmulF(FP_LDOUBLE,res,x,y) #define cdivBiggestF(res,x,y) cdivF(FP_LDOUBLE,res,x,y) #define sqrBiggestF(res,x) sqrF(FP_LDOUBLE,res,x) #define csqrBiggestF(res,x) csqrF(FP_LDOUBLE,res,x) #define fabsBiggestF(res,x) fabsF(FP_LDOUBLE,res,x) #define cabsBiggestF(res,z) cabsF(FP_LDOUBLE,res,z) #define cnormBiggestF(res,z) cnormF(FP_LDOUBLE,res,z) #define crealBiggestF(res,z) crealF(FP_LDOUBLE,res,z) #define cimagBiggestF(res,z) cimagF(FP_LDOUBLE,res,z) #define cargBiggestF(res,z) cargF(FP_LDOUBLE,res,z) #define cpowBiggestF(res,z,y) cpowF(FP_LDOUBLE,res,z,y) #define cipowBiggestF(res,z,y) cipowF(FP_LDOUBLE,res,z,y) #define conjBiggestF(res,z) conjF(FP_LDOUBLE,res,z) #define roundBiggestF(res,x) roundF(FP_LDOUBLE,res,x) #define floorBiggestF(res,x) floorF(FP_LDOUBLE,res,x) #define powBiggestF(res,x,y) powF(FP_LDOUBLE,res,x,y) #define fmaxBiggestF(res,x,y) fmaxF(FP_LDOUBLE,res,x,y) #define modfBiggestF(ires,fres,x) modfF(FP_LDOUBLE,ires,fres,x) #define expBiggestF(res,x) expF(FP_LDOUBLE,res,x) #define logBiggestF(res,x) logF(FP_LDOUBLE,res,x) #define sqrtBiggestF(res,x) sqrtF(FP_LDOUBLE,res,x) #define sinBiggestF(res,x) sinF(FP_LDOUBLE,res,x) #define cosBiggestF(res,x) cosF(FP_LDOUBLE,res,x) #define tanBiggestF(res,x) tanF(FP_LDOUBLE,res,x) #define fromBiggestF(fprec,res,x) fromLDoubleF(fprec,res,x) #define cfromBiggestF(fprec,res,x) cfromCLDoubleF(fprec,res,x) #else // !defined(_ENABLE_MP_FLOATS) && !defined(_ENABLE_LDOUBLE_FLOATS) #define BiggestFloat FLOATTYPE(FP_DOUBLE) #define BiggestComplexFloat COMPLEX_FLOATTYPE(FP_DOUBLE) #define initBiggestF(x) initF(FP_DOUBLE,x) #define clearBiggestF(x) clearF(FP_DOUBLE,x) #define cinitBiggestF(x) cinitF(FP_DOUBLE,x) #define cclearBiggestF(x) cclearF(FP_DOUBLE,x) #define assignBiggestF(dst,src) assignF(FP_DOUBLE,dst,src) #define cassignBiggestF(dst,src) cassignF(FP_DOUBLE,dst,src) #define fromMPFRBiggestF(dst,src) fromMPFRF(FP_DOUBLE,dst,src) #define fromLDoubleBiggestF(dst,src) fromLDoubleF(FP_DOUBLE,dst,src) #define fromDoubleBiggestF(dst,src) fromDoubleF(FP_DOUBLE,dst,src) #define fromUiBiggestF(dst,src) fromUiF(FP_DOUBLE,dst,src) #define fromSiBiggestF(dst,src) fromSiF(FP_DOUBLE,dst,src) #define toDoubleBiggestF(src) toDoubleF(FP_DOUBLE,src) #define cfromMPCBiggestF(dst,src) cfromMPCF(FP_DOUBLE,dst,src) #define cfromCLDoubleBiggestF(dst,src) cfromCLDoubleF(FP_DOUBLE,dst,src) #define cfromUiBiggestF(dst,src) cfromUiF(FP_DOUBLE,dst,src) #define cfromSiBiggestF(dst,src) cfromSiF(FP_DOUBLE,dst,src) #define cfromReImBiggestF(dst,re,im) cfromReImF(FP_DOUBLE,dst,re,im) #define cfromCDoubleBiggestF(dst,src) cfromCDoubleF(FP_DOUBLE,dst,src) #define ctoCDoubleBiggestF(src) ctoCDoubleF(FP_DOUBLE,src) #define cmpBiggestF(x,y) cmpF(FP_DOUBLE,x,y) #define cmp_uiBiggestF(x,y) cmp_uiF(FP_DOUBLE,x,y) #define cmp_siBiggestF(x,y) cmp_siF(FP_DOUBLE,x,y) #define eq_uiBiggestF(x,y) eq_uiF(FP_DOUBLE,x,y) #define eq_siBiggestF(x,y) eq_siF(FP_DOUBLE,x,y) #define ceq_siBiggestF(x,y) ceq_siF(FP_DOUBLE,x,y) #define ceqBiggestF(x,y) ceqF(FP_DOUBLE,x,y) #define cisintegerBiggestF(x) cisintegerF(FP_DOUBLE,x) #define addBiggestF(res,x,y) addF(FP_DOUBLE,res,x,y) #define subBiggestF(res,x,y) subF(FP_DOUBLE,res,x,y) #define mulBiggestF(res,x,y) mulF(FP_DOUBLE,res,x,y) #define divBiggestF(res,x,y) divF(FP_DOUBLE,res,x,y) #define add_dBiggestF(res,x,y) add_dF(FP_DOUBLE,res,x,y) #define sub_dBiggestF(res,x,y) sub_dF(FP_DOUBLE,res,x,y) #define mul_dBiggestF(res,x,y) mul_dF(FP_DOUBLE,res,x,y) #define div_dBiggestF(res,x,y) div_dF(FP_DOUBLE,res,x,y) #define add_uiBiggestF(res,x,y) add_uiF(FP_DOUBLE,res,x,y) #define sub_uiBiggestF(res,x,y) sub_uiF(FP_DOUBLE,res,x,y) #define mul_uiBiggestF(res,x,y) mul_uiF(FP_DOUBLE,res,x,y) #define div_uiBiggestF(res,x,y) div_uiF(FP_DOUBLE,res,x,y) #define add_siBiggestF(res,x,y) add_siF(FP_DOUBLE,res,x,y) #define sub_siBiggestF(res,x,y) sub_siF(FP_DOUBLE,res,x,y) #define mul_siBiggestF(res,x,y) mul_siF(FP_DOUBLE,res,x,y) #define div_siBiggestF(res,x,y) div_siF(FP_DOUBLE,res,x,y) #define caddBiggestF(res,x,y) caddF(FP_DOUBLE,res,x,y) #define csubBiggestF(res,x,y) csubF(FP_DOUBLE,res,x,y) #define cmulBiggestF(res,x,y) cmulF(FP_DOUBLE,res,x,y) #define cdivBiggestF(res,x,y) cdivF(FP_DOUBLE,res,x,y) #define sqrBiggestF(res,x) sqrF(FP_DOUBLE,res,x) #define csqrBiggestF(res,x) csqrF(FP_DOUBLE,res,x) #define fabsBiggestF(res,x) fabsF(FP_DOUBLE,res,x) #define cabsBiggestF(res,z) cabsF(FP_DOUBLE,res,z) #define cnormBiggestF(res,z) cnormF(FP_DOUBLE,res,z) #define crealBiggestF(res,z) crealF(FP_DOUBLE,res,z) #define cimagBiggestF(res,z) cimagF(FP_DOUBLE,res,z) #define cargBiggestF(res,z) cargF(FP_DOUBLE,res,z) #define cpowBiggestF(res,z,y) cpowF(FP_DOUBLE,res,z,y) #define cipowBiggestF(res,z,y) cipowF(FP_DOUBLE,res,z,y) #define conjBiggestF(res,z) conjF(FP_DOUBLE,res,z) #define roundBiggestF(res,x) roundF(FP_DOUBLE,res,x) #define floorBiggestF(res,x) floorF(FP_DOUBLE,res,x) #define powBiggestF(res,x,y) powF(FP_DOUBLE,res,x,y) #define fmaxBiggestF(res,x,y) fmaxF(FP_DOUBLE,res,x,y) #define modfBiggestF(ires,fres,x) modfF(FP_DOUBLE,ires,fres,x) #define expBiggestF(res,x) expF(FP_DOUBLE,res,x) #define logBiggestF(res,x) logF(FP_DOUBLE,res,x) #define sqrtBiggestF(res,x) sqrtF(FP_DOUBLE,res,x) #define sinBiggestF(res,x) sinF(FP_DOUBLE,res,x) #define cosBiggestF(res,x) cosF(FP_DOUBLE,res,x) #define tanBiggestF(res,x) tanF(FP_DOUBLE,res,x) #define fromBiggestF(fprec,res,x) fromDoubleF(fprec,res,x) #define cfromBiggestF(fprec,res,x) cfromCDoubleF(fprec,res,x) #endif /*********************************************************/ #define DECL_FLOAT(fprec,x) FLOATTYPE(fprec) x #define DECL_COMPLEX_FLOAT(fprec,x) COMPLEX_FLOATTYPE(fprec) x #define DECL_INIT_FLOAT(fprec,x) \ DECL_FLOAT(fprec,x);\ initF(fprec,x) #define DECL_INIT_COMPLEX_FLOAT(fprec,x) \ DECL_COMPLEX_FLOAT(fprec,x);\ cinitF(fprec,x) #define FLOAT_VAR(fprec,x) x##_##fprec #define AUX_DECL_MULTI_FLOAT(fprec,x) DECL_FLOAT(fprec,FLOAT_VAR(fprec,x)) #define AUX_DECL_MULTI_COMPLEX_FLOAT(fprec,x) DECL_COMPLEX_FLOAT(fprec,FLOAT_VAR(fprec,x)) #define AUX_INIT_MULTI_FLOAT(fprec,x) initF(fprec,FLOAT_VAR(fprec,x)) #define AUX_INIT_MULTI_COMPLEX_FLOAT(fprec,x) cinitF(fprec,FLOAT_VAR(fprec,x)) #define AUX_CLEAR_MULTI_FLOAT(fprec,x) clearF(fprec,FLOAT_VAR(fprec,x)) #define AUX_CLEAR_MULTI_COMPLEX_FLOAT(fprec,x) cclearF(fprec,FLOAT_VAR(fprec,x)) /***********************MULTI FLOATS**********************/ #if (defined(_ENABLE_MP_FLOATS) && defined(_ENABLE_LDOUBLE_FLOATS)) #define DECL_MULTI_FLOAT(x) \ AUX_DECL_MULTI_FLOAT(FP_SINGLE,x);\ AUX_DECL_MULTI_FLOAT(FP_DOUBLE,x);\ AUX_DECL_MULTI_FLOAT(FP_LDOUBLE,x);\ AUX_DECL_MULTI_FLOAT(FP_MP,x) #define DECL_MULTI_COMPLEX_FLOAT(x) \ AUX_DECL_MULTI_COMPLEX_FLOAT(FP_SINGLE,x);\ AUX_DECL_MULTI_COMPLEX_FLOAT(FP_DOUBLE,x);\ AUX_DECL_MULTI_COMPLEX_FLOAT(FP_LDOUBLE,x);\ AUX_DECL_MULTI_COMPLEX_FLOAT(FP_MP,x) #define INIT_MULTI_FLOAT(x) \ AUX_INIT_MULTI_FLOAT(FP_SINGLE,x);\ AUX_INIT_MULTI_FLOAT(FP_DOUBLE,x);\ AUX_INIT_MULTI_FLOAT(FP_LDOUBLE,x);\ AUX_INIT_MULTI_FLOAT(FP_MP,x) #define INIT_MULTI_COMPLEX_FLOAT(x) \ AUX_INIT_MULTI_COMPLEX_FLOAT(FP_SINGLE,x);\ AUX_INIT_MULTI_COMPLEX_FLOAT(FP_DOUBLE,x);\ AUX_INIT_MULTI_COMPLEX_FLOAT(FP_LDOUBLE,x);\ AUX_INIT_MULTI_COMPLEX_FLOAT(FP_MP,x) #define CLEAR_MULTI_FLOAT(x) \ AUX_CLEAR_MULTI_FLOAT(FP_SINGLE,x);\ AUX_CLEAR_MULTI_FLOAT(FP_DOUBLE,x);\ AUX_CLEAR_MULTI_FLOAT(FP_LDOUBLE,x);\ AUX_CLEAR_MULTI_FLOAT(FP_MP,x) #define CLEAR_MULTI_COMPLEX_FLOAT(x) \ AUX_CLEAR_MULTI_COMPLEX_FLOAT(FP_SINGLE,x);\ AUX_CLEAR_MULTI_COMPLEX_FLOAT(FP_DOUBLE,x);\ AUX_CLEAR_MULTI_COMPLEX_FLOAT(FP_LDOUBLE,x);\ AUX_CLEAR_MULTI_COMPLEX_FLOAT(FP_MP,x) #define AUX_ASSIGN_MULTI_FLOAT(fprec,dst,src) \ fromBiggestF(fprec,FLOAT_VAR(fprec,dst),src) #define ASSIGN_MULTI_FLOAT(dst,src) \ AUX_ASSIGN_MULTI_FLOAT(FP_SINGLE,dst,src);\ AUX_ASSIGN_MULTI_FLOAT(FP_DOUBLE,dst,src);\ AUX_ASSIGN_MULTI_FLOAT(FP_LDOUBLE,dst,src);\ AUX_ASSIGN_MULTI_FLOAT(FP_MP,dst,src) #define AUX_ASSIGN_MULTI_COMPLEX_FLOAT(fprec,dst,src) \ cfromBiggestF(fprec,FLOAT_VAR(fprec,dst),src) #define ASSIGN_MULTI_COMPLEX_FLOAT(dst,src) \ AUX_ASSIGN_MULTI_COMPLEX_FLOAT(FP_SINGLE,dst,src);\ AUX_ASSIGN_MULTI_COMPLEX_FLOAT(FP_DOUBLE,dst,src);\ AUX_ASSIGN_MULTI_COMPLEX_FLOAT(FP_LDOUBLE,dst,src);\ AUX_ASSIGN_MULTI_COMPLEX_FLOAT(FP_MP,dst,src) #elif (defined(_ENABLE_MP_FLOATS) && !defined(_ENABLE_LDOUBLE_FLOATS)) #define DECL_MULTI_FLOAT(x) \ AUX_DECL_MULTI_FLOAT(FP_SINGLE,x);\ AUX_DECL_MULTI_FLOAT(FP_DOUBLE,x);\ AUX_DECL_MULTI_FLOAT(FP_MP,x) #define DECL_MULTI_COMPLEX_FLOAT(x) \ AUX_DECL_MULTI_COMPLEX_FLOAT(FP_SINGLE,x);\ AUX_DECL_MULTI_COMPLEX_FLOAT(FP_DOUBLE,x);\ AUX_DECL_MULTI_COMPLEX_FLOAT(FP_MP,x) #define INIT_MULTI_FLOAT(x) \ AUX_INIT_MULTI_FLOAT(FP_SINGLE,x);\ AUX_INIT_MULTI_FLOAT(FP_DOUBLE,x);\ AUX_INIT_MULTI_FLOAT(FP_MP,x) #define INIT_MULTI_COMPLEX_FLOAT(x) \ AUX_INIT_MULTI_COMPLEX_FLOAT(FP_SINGLE,x);\ AUX_INIT_MULTI_COMPLEX_FLOAT(FP_DOUBLE,x);\ AUX_INIT_MULTI_COMPLEX_FLOAT(FP_MP,x); #define CLEAR_MULTI_FLOAT(x) \ AUX_CLEAR_MULTI_FLOAT(FP_SINGLE,x);\ AUX_CLEAR_MULTI_FLOAT(FP_DOUBLE,x);\ AUX_CLEAR_MULTI_FLOAT(FP_MP,x) #define CLEAR_MULTI_COMPLEX_FLOAT(x) \ AUX_CLEAR_MULTI_COMPLEX_FLOAT(FP_SINGLE,x);\ AUX_CLEAR_MULTI_COMPLEX_FLOAT(FP_DOUBLE,x);\ AUX_CLEAR_MULTI_COMPLEX_FLOAT(FP_MP,x) #define AUX_ASSIGN_MULTI_FLOAT(fprec,dst,src) \ fromBiggestF(fprec,FLOAT_VAR(fprec,dst),src) #define ASSIGN_MULTI_FLOAT(dst,src) \ AUX_ASSIGN_MULTI_FLOAT(FP_SINGLE,dst,src);\ AUX_ASSIGN_MULTI_FLOAT(FP_DOUBLE,dst,src);\ AUX_ASSIGN_MULTI_FLOAT(FP_MP,dst,src) #define AUX_ASSIGN_MULTI_COMPLEX_FLOAT(fprec,dst,src) \ cfromBiggestF(fprec,FLOAT_VAR(fprec,dst),src) #define ASSIGN_MULTI_COMPLEX_FLOAT(dst,src) \ AUX_ASSIGN_MULTI_COMPLEX_FLOAT(FP_SINGLE,dst,src);\ AUX_ASSIGN_MULTI_COMPLEX_FLOAT(FP_DOUBLE,dst,src);\ AUX_ASSIGN_MULTI_COMPLEX_FLOAT(FP_MP,dst,src) #elif (!defined(_ENABLE_MP_FLOATS) && defined(_ENABLE_LDOUBLE_FLOATS)) #define DECL_MULTI_FLOAT(x) \ AUX_DECL_MULTI_FLOAT(FP_SINGLE,x);\ AUX_DECL_MULTI_FLOAT(FP_DOUBLE,x);\ AUX_DECL_MULTI_FLOAT(FP_LDOUBLE,x) #define DECL_MULTI_COMPLEX_FLOAT(x) \ AUX_DECL_MULTI_COMPLEX_FLOAT(FP_SINGLE,x);\ AUX_DECL_MULTI_COMPLEX_FLOAT(FP_DOUBLE,x);\ AUX_DECL_MULTI_COMPLEX_FLOAT(FP_LDOUBLE,x) #define INIT_MULTI_FLOAT(x) \ AUX_INIT_MULTI_FLOAT(FP_SINGLE,x);\ AUX_INIT_MULTI_FLOAT(FP_DOUBLE,x);\ AUX_INIT_MULTI_FLOAT(FP_LDOUBLE,x) #define INIT_MULTI_COMPLEX_FLOAT(x) \ AUX_INIT_MULTI_COMPLEX_FLOAT(FP_SINGLE,x);\ AUX_INIT_MULTI_COMPLEX_FLOAT(FP_DOUBLE,x);\ AUX_INIT_MULTI_COMPLEX_FLOAT(FP_LDOUBLE,x); #define CLEAR_MULTI_FLOAT(x) \ AUX_CLEAR_MULTI_FLOAT(FP_SINGLE,x);\ AUX_CLEAR_MULTI_FLOAT(FP_DOUBLE,x);\ AUX_CLEAR_MULTI_FLOAT(FP_LDOUBLE,x) #define CLEAR_MULTI_COMPLEX_FLOAT(x) \ AUX_CLEAR_MULTI_COMPLEX_FLOAT(FP_SINGLE,x);\ AUX_CLEAR_MULTI_COMPLEX_FLOAT(FP_DOUBLE,x);\ AUX_CLEAR_MULTI_COMPLEX_FLOAT(FP_LDOUBLE,x) #define AUX_ASSIGN_MULTI_FLOAT(fprec,dst,src) \ fromBiggestF(fprec,FLOAT_VAR(fprec,dst),src) #define ASSIGN_MULTI_FLOAT(dst,src) \ AUX_ASSIGN_MULTI_FLOAT(FP_SINGLE,dst,src);\ AUX_ASSIGN_MULTI_FLOAT(FP_DOUBLE,dst,src);\ AUX_ASSIGN_MULTI_FLOAT(FP_LDOUBLE,dst,src) #define AUX_ASSIGN_MULTI_COMPLEX_FLOAT(fprec,dst,src) \ cfromBiggestF(fprec,FLOAT_VAR(fprec,dst),src) #define ASSIGN_MULTI_COMPLEX_FLOAT(dst,src) \ AUX_ASSIGN_MULTI_COMPLEX_FLOAT(FP_SINGLE,dst,src);\ AUX_ASSIGN_MULTI_COMPLEX_FLOAT(FP_DOUBLE,dst,src);\ AUX_ASSIGN_MULTI_COMPLEX_FLOAT(FP_LDOUBLE,dst,src) #else // !defined(_ENABLE_MP_FLOATS) && !defined(_ENABLE_LDOUBLE_FLOATS) #define DECL_MULTI_FLOAT(x) \ AUX_DECL_MULTI_FLOAT(FP_SINGLE,x);\ AUX_DECL_MULTI_FLOAT(FP_DOUBLE,x) #define DECL_MULTI_COMPLEX_FLOAT(x) \ AUX_DECL_MULTI_COMPLEX_FLOAT(FP_SINGLE,x);\ AUX_DECL_MULTI_COMPLEX_FLOAT(FP_DOUBLE,x) #define INIT_MULTI_FLOAT(x) \ AUX_INIT_MULTI_FLOAT(FP_SINGLE,x);\ AUX_INIT_MULTI_FLOAT(FP_DOUBLE,x) #define INIT_MULTI_COMPLEX_FLOAT(x) \ AUX_INIT_MULTI_COMPLEX_FLOAT(FP_SINGLE,x);\ AUX_INIT_MULTI_COMPLEX_FLOAT(FP_DOUBLE,x) #define CLEAR_MULTI_FLOAT(x) \ AUX_CLEAR_MULTI_FLOAT(FP_SINGLE,x);\ AUX_CLEAR_MULTI_FLOAT(FP_DOUBLE,x) #define CLEAR_MULTI_COMPLEX_FLOAT(x) \ AUX_CLEAR_MULTI_COMPLEX_FLOAT(FP_SINGLE,x);\ AUX_CLEAR_MULTI_COMPLEX_FLOAT(FP_DOUBLE,x) #define AUX_ASSIGN_MULTI_FLOAT(fprec,dst,src) \ fromBiggestF(fprec,FLOAT_VAR(fprec,dst),src) #define ASSIGN_MULTI_FLOAT(dst,src) \ AUX_ASSIGN_MULTI_FLOAT(FP_SINGLE,dst,src);\ AUX_ASSIGN_MULTI_FLOAT(FP_DOUBLE,dst,src) #define AUX_ASSIGN_MULTI_COMPLEX_FLOAT(fprec,dst,src) \ cfromBiggestF(fprec,FLOAT_VAR(fprec,dst),src) #define ASSIGN_MULTI_COMPLEX_FLOAT(dst,src) \ AUX_ASSIGN_MULTI_COMPLEX_FLOAT(FP_SINGLE,dst,src);\ AUX_ASSIGN_MULTI_COMPLEX_FLOAT(FP_DOUBLE,dst,src) #endif /*********************************************************/ #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/lib/include/image.h000664 001750 001750 00000020417 13175112471 017237 0ustar00mpegmpeg000000 000000 /* * image.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file image.h * \brief Header file related to images. * \author Marc Pegon */ #ifndef __IMAGE_H__ #define __IMAGE_H__ #include "error.h" #include "color.h" #include "task.h" #include #ifdef __cplusplus extern "C" { #endif /** * \struct Image * \brief Simple RGB image. * * A 2D array of colors representing an image.\n * RGB8 images pixels are stored using uint32_t (the * most significant 8 bits are not used (0xFF)).\n * RGB16 images pixels are stored using uint64_t bytes (the * most significant 16 bites are not used (0xFFFF)). */ /** * \typedef Image * \brief Convenient typedef for struct Image. */ typedef struct Image { uint8_t *data; /*!< Imaga data : 32-bits aligned.*/ int data_is_external; /*!< 1 if data should not be freed by Image structure.*/ uint_fast32_t width; /*!< Image width.*/ uint_fast32_t height; /*!< Image height.*/ uint_fast8_t bytesPerComponent; /*!< Colors bytes per component.*/ } Image; /** * \fn void CreateImage(Image *image, uint_fast32_t width, uint_fast32_t height, uint_fast8_t bytesPerComponent) * \brief Create an image. * * Create a (black) image of given width and height. * * \param image Pointer to image structure to create. * \param width Image width. * \param height Image height. * \param bytesPerComponent Colors bytes per component. */ void CreateImage(Image *image, uint_fast32_t width, uint_fast32_t height, uint_fast8_t bytesPerComponent); /** * \fn void CreateImage2(Image *image, uint8_t *data, uint_fast32_t width, uint_fast32_t height, uint_fast8_t bytesPerComponent) * \brief Create an image using an already allocated data array. * * Data format must be as described in image structure.\n * Remark : in this case data will be *not* be free'd * by FreeImage, and must stay alive as long as image is * used. * * \param image Pointer to image structure to create. * \param data Image data to use for image. * \param width Image width. * \param height Image height. * \param bytesPerComponent Colors bytes per component. */ void CreateImage2(Image *image, uint8_t *data, uint_fast32_t width, uint_fast32_t height, uint_fast8_t bytesPerComponent); /** * \fn Image CloneImage(const Image *image) * \brief Copy image. * * \param image Pointer to image to be copied. * \return Copy of image. */ Image CloneImage(const Image *image); /** * \fn uint8_t *ImageToBytesArray(const Image *image) * \brief Convert image to bytes array. * * For RGB8 images : the returned bytes array is the sequence r1 g1 b1 r2 g2 b2, etc., * without padding (not 32-bits aligned).\n * For RGB16 images : the returned bytes array is the sequence r1h r1l g1h g1l * b1h b1l r2h r2b g2h g2l b2h b2l (h for high (MSB), and l for low (LSB)). * without padding (not 32-bits aligned). \n * Return NULL if image is empty (width and/or height = 0). * * Thus the array size (in bytes) is width*height*3*bytesPerComponent.\n * Convenient to write directly a binary PPM file for example. * * \param image Image to convert to bytes array. * \return Copy of image data. */ uint8_t *ImageToBytesArray(const Image *image); /** * \fn Color iGetPixelUnsafe(const Image *image, uint_fast32_t x, uint_fast32_t y) * \brief Get some pixel of image. * * Get pixel (x,y) of image.\n * Warning : the function does not check that (x,y) * is actually a point inside image. * * \param image Image to get pixel from. * \param x X pixel coordinate. * \param y Y pixel coordinate. * \return Color at position (x,y) of image. */ Color iGetPixelUnsafe(const Image *image, uint_fast32_t x, uint_fast32_t y); /** * \fn Color iGetPixel(const Image *image, int_fast64_t x, int_fast64_t y) * \brief Get some pixel of image. * * Get pixel (x,y) of image.\n * (x,y) can be a point outside image : pixels outside image * are duplicates of the pixels at the sides of it. * * \param image Image to get pixel from. * \param x X pixel coordinate. * \param y Y pixel coordinate. * \return Color at position (x,y) of image. */ Color iGetPixel(const Image *image, int_fast64_t x, int_fast64_t y); /** * \fn void PutPixelUnsafe(Image *image, uint_fast32_t x, uint_fast32_t y, Color color) * \brief Put pixel at some particular position in image. * * Put pixel at position (x,y) of image.\n * Warning : the function does not check that (x,y) * is actually a point inside image.\n * Color format must be the same as image format * (undefined behaviour otherwise). * * \param image Image to put pixel to. * \param x X pixel coordinate. * \param y Y pixel coordinate. * \param color Color to put at position (x,y) of image. */ void PutPixelUnsafe(Image *image, uint_fast32_t x, uint_fast32_t y, Color color); /** * \fn void ApplyGaussianBlur(Image *dst, const Image *src, double radius, Threads *threads) * \brief Apply gaussian blur on image. * * This function does no work in place.\n * Applies successively a horizontal and vertical gaussian filter * to avoid quadratic computation cost. * * \param dst Pointer to already created destination image. * \param src Pointer to source image (to apply blur on). * \param radius Gaussian blur radius. * \param threads Threads to be used for task. */ void ApplyGaussianBlur(Image *dst, const Image *src, double radius, Threads *threads); /** * \fn Task *CreateApplyGaussianBlurTask(Image *dst, Image *temp, const Image *src, double radius, uint_fast32_t nbThreads) * \brief Create task applying a gaussian blur. * * Create task and return immediately.\n * Number of threads is used to create a task adapted * to a specific number of threads.\n * When launching task, Threads structure should provide * enough threads (at least number specified here). * * \param dst Pointer to already created destination image. * \param temp Pointer to temporary image (needed to apply blur). * \param src Pointer to source image (to apply blur on). * \param radius Gaussian blur radius. * \param nbThreads Number of threads that action will need to be launched. * \return Corresponding newly-allocated task. */ Task *CreateApplyGaussianBlurTask(Image *dst, Image *temp, const Image *src, double radius, uint_fast32_t nbThreads); /** * \fn void DownscaleImage(Image *dst, const Image *src, Threads *threads) * \brief Downscale image. * * Destination image must already have been created, and its size * (both with and height) must be greater than that of the source * (exit with error otherwise). * * \param dst Pointer to already created destination image. * \param src Pointer to source image (to be downscaled). * \param threads Threads to be used for task. */ void DownscaleImage(Image *dst, const Image *src, Threads *threads); /** * \fn Task *CreateDownscaleImageTask(Image *dst, const Image *src, uint_fast32_t nbThreads) * \brief Create task downscaling an image. * * Create task and return immediately.\n * Number of threads is used to create a task adapted * to a specific number of threads.\n * When launching task, Threads structure should provide * enough threads (at least number specified here). * * \param dst Pointer to already created destination image. * \param src Pointer to source image (to be downscaled). * \param nbThreads Number of threads that action will need to be launched. * \return Corresponding (newly-allocated) task. */ Task *CreateDownscaleImageTask(Image *dst, const Image *src, uint_fast32_t nbThreads); /** * \fn void FreeImage(Image image) * \brief Free image. * * \param image Image to free. */ void FreeImage(Image image); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/gui/src/help.cpp000664 001750 001750 00000007616 13175112471 016630 0ustar00mpegmpeg000000 000000 /* * help.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "help.h" #include "main.h" #include #include void Help::Print() { printf("qfractalnow v%s - Explore fractals and generate \ fractal images.\n\n\ Usage : qfractalnow [OPTIONS]\n\n\ OPTIONS:\n\ -h Prints this help.\n\ -q Quiet mode.\n\ -v Verbose mode.\n" #ifdef DEBUG " -d Debug mode.\n" #endif " -j Specify number of threads \ (%"PRIuFAST32" by default).\n\ -c Specify configuration file, \ overriding default configuration.\n\ -f Specify fractal file, overriding \ parameters from default configuration or configuration file.\n\ -r Specify rendering file, overriding \ parameters from default configuration or configuration file.\n\ -g Specify gradient file, overriding \ gradient from default configuration, configuration file, or \ rendering file.\n\ -x Specify image width.\n\ -y Specify image height.\n\ -l Specify float precision:\n\ single Single precision.\n\ double Double precision.\n" #ifdef _ENABLE_LDOUBLE_FLOATS " ldouble Long double \ precision.\n" #endif #ifdef _ENABLE_MP_FLOATS " mp Multiple \ precision.\n\ -L Specify precision for Multiple \ Precision (MP) floats (%"PRId64" by default).\n" #endif " -m Specify minimum size of adaptive \ anti-aliasing (%"PRIuFAST32" by default).\n\ Must be an integer strictly greater \ than 1.\n\ -M Specify maximum size of adaptive \ anti-aliasing (%"PRIuFAST32" by default).\n\ Must be an integer strictly greater \ than 1 and MinAAMSize.\n\ -n Anti-aliasing size iteration.\n\ Anti-aliasing size will increase by \ steps of AAMSizeIteration from MinAAMSize to MaxAAMSize.\n\ -p Threshold for adaptive \ anti-aliasing (%G by default).\n\ -i Maximum size of quadrilaterals for \ linear interpolation.\n\ %"PRIuFAST32" by default, which is \ good for no visible loss of quality.\n\ 1 means no interpolation (all \ pixels are computed).\n\ -t Dissimilarity threshold for quad \ interpolation.\n\ %G by default, which is \ good for no visible loss of quality.\n\ A quadrilateral that shows too \ dissimilar values at its corners will be computed, \ as opposed to interpolated.\n", FractalNow_VersionNumber(), DEFAULT_NB_THREADS, #ifdef _ENABLE_MP_FLOATS DEFAULT_MP_PRECISION, #endif DEFAULT_MIN_ANTIALIASING_SIZE, DEFAULT_MAX_ANTIALIASING_SIZE, DEFAULT_ADAPTIVE_AAM_THRESHOLD, DEFAULT_QUAD_INTERPOLATION_SIZE, DEFAULT_COLOR_DISSIMILARITY_THRESHOLD); } fractalnow-0.8.2/lib/src/fractal_transfer_function.c000664 001750 001750 00000005224 13175112471 022540 0ustar00mpegmpeg000000 000000 /* * fractal_transfer_function.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "fractal_transfer_function.h" #include "error.h" #include "misc.h" #include #include #include double logp1logp1(double x) { return log(log(1+x)+1); } double logp1(double x) { return log(1+x); } double cubert(double x) { return pow(x, 1./3); } double identity(double x) { return x; } double square(double x) { return x*x; } double cube(double x) { return x*x*x; } const TransferFunctionPtr transferFunctionsArray[] = { logp1logp1, logp1, cubert, sqrt, identity, square, cube, exp }; const char *transferFunctionStr[] = { (const char *)"loglog", (const char *)"log", (const char *)"cuberoot", (const char *)"squareroot", (const char *)"identity", (const char *)"square", (const char *)"cube", (const char *)"exp" }; const char *transferFunctionDescStr[] = { (const char *)"Log log", (const char *)"Logarithm", (const char *)"Cube root", (const char *)"Square root", (const char *)"Identity", (const char *)"Square", (const char *)"Cube", (const char *)"Exponential" }; const uint_fast32_t nbTransferFunctions = sizeof(transferFunctionStr) / sizeof(const char *); int GetTransferFunction(TransferFunction *transferFunction, const char *str) { int res = 0; size_t len = strlen(str); if (len > 255) { FractalNow_werror("Unknown transfer function \'%s\'.\n", str); } char TFStr[256]; strcpy(TFStr, str); toLowerCase(TFStr); uint_fast32_t i; for (i = 0; i < nbTransferFunctions; ++i) { if (strcmp(TFStr, transferFunctionStr[i]) == 0) { *(transferFunction) = (TransferFunction)i; break; } } if (i == nbTransferFunctions) { FractalNow_werror("Unknown transfer function \'%s\'.\n", str); } end: return res; } TransferFunctionPtr GetTransferFunctionPtr(TransferFunction transferFunction) { return transferFunctionsArray[(int)transferFunction]; } fractalnow-0.8.2/000775 001750 001750 00000000000 13175155036 013613 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/gui/icons/icon48x48.png000664 001750 001750 00000010445 13175112471 017670 0ustar00mpegmpeg000000 000000 PNG  IHDR00WgAMA asRGB cHRMz&u0`:pQ<bKGDC pHYs   vpAg00WIDAThޝ{eW]?k}N{;̣(-@ i$bX䏪 $FHMH4T(*JR6Wfh3ܙ;syY{;@g%'sZ^W=PSN5^J4ZC@&ְX@U~i^At:}lE*QCQxaǑUE<3:MՇ}P|~x:W<bHӗu!p(jr]aua>q,cbqƗK8$|5F)Ue+Af,Q/<C̈́e_Y6{ı!MJA,2TU䜥CkyYű\HC#,rkBQU8v8P#&HB6Bк6@l:M :C(1 㨕a],mh-Z*p(Ĝ:d0td/Hh>W *A%@$͊AQUvgCoIRtS{oxNVK,a0;;r,˥poLS L-mo|2QDhuŗ|_abc+ IH I ZC'wz"RXL%hiNXݮ@SUѣC |!IeyS_7t@)1]%U_5,j U+XRT\˜1}%@DG_ g"Y[/x>pvF\7Fk,S +ixW:#FAˈ1Z._V1if%1`Ph8JLy5$K %4E!I|3qܡHw#(5u Κ Ma2L6-vQX̟\ɴZ6=Ph+hj-)ww+&2oc }{{qMɯj Z[߽&JSJa<mQ:Xݧ\fc%}7exKͩJ14Yguo9;}s?.~p_' CA<Y&q6rnL(D+DWQTa'~tnk7gr /]ܔٝG, +$ϜoU!ۀcqv[b>W٤@a6#"8fq JAܓ?_~bE&yN'Q="b"υTkE!8␛*aB)\Z3ݠ~u JoS3׷.ri΃ AN{IZ7l6Ph 6QJB{PVKgp]?rkOп&y~ OmO_v=-xGLP' ݮttĎmnqp uAgp]$nD ^Ǿ1NO|͔o|wCyU TƠ #LꠔYE{r)r)A5h-` Y%QxU} ykjBG|譚 fWE<tw{8޵T l({=CvnAghW=loէ1Z[m:V*ZV~//[z~_$땜:5$=CYc)Ͼ?Ӭ$7Kn0pySU/nN3_z(eCE:ISVip=)l:$HJU,u:l=@GzgSfաdsq׽-,>RR ˥8t \! b,]LQ 7Ƚx0nqkNoqSъKg="s*exE3e=sE!UHT 9书oJڔzo~)F?f =In"o {bTbRU@,=AƑY I%R$r`oO>CrBNAT(ʿ3=߼^6]U'cȶ|ᛦMm$0._n5oi|(quPj(J9j?EYqfgϒtW?xV;Y&NG tud"j=aعk鴿N>Cz?yUj{TUXdGɲ1V-h?ݶR3F,4҅HSb@TQ5Y7W8uKsxs?Rl2?$EnsH1 M,ԓ ul== ˥rݦEHq))ðb:U乤Uۡ*~7?p N_!6>2+6q \Id*);bZ.՘-r֛Ib0Fgx C|.擦bEZ$ws_n}er#UhYq]rKUh7p0>pPU$. 3@H ll&d+;LXUlbAIR2ioI[]mxEK+(]Oa3L.Ye8ض5Fɲ*QKyGZ-MR-ˠ1fs! =mMu0|GT=ﻅzqk5Su[+>VUJIPϓ`6k°o3&f(;8):Z'-'oϡz/U &\ Qd^5q̀RMC ` mH8l_PYiKɗ$a(6FJG Qw&lh־c5e" uK<Ā.H hAYFJl#;2Ǒm^kanwW] Əwq0S[㠵YiX_uE&mVN(ݹmI_Jn:֩.]԰LQ7C;ec4Iv <0l9TjmBcҷr)fnǂˣHB㈙ C;;wO: hf>zW;"q8[raoO\2ZCpp 2Cu٬17C:4űPk!|gjfec.9DzW{0i @Ch.OpMl3@)SK9X48ژ¸ʲjN]G[z\NtL` 0Jl_֎QZ%tEXtdate:create2012-05-27T10:48:29+02:00+b%tEXtdate:modify2012-05-27T10:48:29+02:00qIENDB`fractalnow-0.8.2/lib/src/fractal_coloring.c000664 001750 001750 00000005207 13175115345 020627 0ustar00mpegmpeg000000 000000 /* * fractal_coloring.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "fractal.h" #include "fractal_coloring.h" #include "misc.h" #include const char *coloringMethodStr[] = { (char *)"iterationcount", (char *)"averagecoloring" }; const char *coloringMethodDescStr[] = { (char *)"Iteration count", (char *)"Average coloring" }; const uint_fast32_t nbColoringMethods = sizeof(coloringMethodStr) / sizeof(char *); int GetColoringMethod(ColoringMethod *coloringMethod, const char *str) { int res = 0; int len = strlen(str); if (len > 255) { FractalNow_werror("Unknown coloring method \'%s\'.\n", str); } char CMStr[256]; strcpy(CMStr, str); toLowerCase(CMStr); uint_fast32_t i; for (i = 0; i < nbColoringMethods; ++i) { if (strcmp(CMStr, coloringMethodStr[i]) == 0) { *coloringMethod = (ColoringMethod)i; break; } } if (i == nbColoringMethods) { FractalNow_werror("Unknown coloring method \'%s\'.\n", str); } end: return res; } const char *interpolationMethodStr[] = { (const char *)"none", (const char *)"linear", (const char *)"spline" }; const char *interpolationMethodDescStr[] = { (const char *)"None", (const char *)"Linear", (const char *)"Spline" }; const uint_fast32_t nbInterpolationMethods = sizeof(interpolationMethodStr) / sizeof(const char *); int GetInterpolationMethod(InterpolationMethod *interpolationMethod, const char *str) { int res = 0; int len = strlen(str); if (len > 255) { FractalNow_werror("Unknown interpolation method \'%s\'.\n", str); } char IMStr[256]; strcpy(IMStr, str); toLowerCase(IMStr); uint_fast32_t i; for (i = 0; i < nbInterpolationMethods; ++i) { if (strcmp(IMStr, interpolationMethodStr[i]) == 0) { *interpolationMethod = (InterpolationMethod)i; break; } } if (i == nbInterpolationMethods) { FractalNow_werror("Unknown interpolation method \'%s\'.\n", str); } end: return res; } fractalnow-0.8.2/lib/include/misc.h000664 001750 001750 00000005652 13175115345 017117 0ustar00mpegmpeg000000 000000 /* * misc.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file misc.h * \brief Header file containing miscellaneous functions. * \author Marc Pegon */ #ifndef __MISC_H__ #define __MISC_H__ #include "float_precision.h" #include #include #ifdef __cplusplus extern "C" { #endif /** * \def UNUSED(x) * \brief Macro for unused variables. */ #define UNUSED(x) (void)x /** * \fn void toLowerCase(char *str) * \brief Convert string letter to lower case. * * str must be NULL-terminated (undefined behabiour * otherwise). * * \param str String to convert. */ void toLowerCase(char *str); /** * \fn void *safeMalloc(const char *name, uint_least64_t size) * \brief Safe memory allocation. * * Exit with error if memory allocation fails. * * \param name Name to print in case of allocation failure. * \param size Number of bytes to allocate. * \return Pointer to the allocated memory. */ void *safeMalloc(const char *name, uint_least64_t size); /** * \fn void *safeRealloc(const char *name, void *ptr, uint_least64_t size) * \brief Safe memory reallocation. * * Exit with error if memory reallocation fails. * * \param name Name to print in case of allocation failure. * \param ptr Pointer to memory to reallocate. * \param size Number of bytes to allocate. * \return Pointer to the allocated memory. */ void *safeRealloc(const char *name, void *ptr, uint_least64_t size); /** * \fn void void *safeCalloc(const char *name, uint_least64_t nmemb, uint_least64_t size) * \brief Safe memory allocation. * * Exit with error if memory allocation fails. * * \param name Name to print in case of allocation failure. * \param nmemb Number of elements in array to allocate. * \param size Size of each element in bytes. * \return Pointer to the allocated memory. */ void *safeCalloc(const char *name, uint_least64_t nmemb, uint_least64_t size); #ifdef _ENABLE_MP_FLOATS /** * \fn int mpcIsInteger(const mpc_t x) * \brief Test if a mpc complex is a (real) integer. * * \param x Complex to be tested. * \return 1 if complex is a (real) integer, 0 otherwise. */ int mpcIsInteger(const mpc_t x); #endif #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/lib/src/float_precision.c000664 001750 001750 00000005132 13175115345 020474 0ustar00mpegmpeg000000 000000 /* * float_precision.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "error.h" #include "float_precision.h" #include "misc.h" #include const char *floatPrecisionStr[] = { (const char *)"single", (const char *)"double", #ifdef _ENABLE_LDOUBLE_FLOATS (const char *)"ldouble", #endif #ifdef _ENABLE_MP_FLOATS (const char *)"mp" #endif }; const char *floatPrecisionDescStr[] = { (const char *)"Single", (const char *)"Double", #ifdef _ENABLE_LDOUBLE_FLOATS (const char *)"Long double", #endif #ifdef _ENABLE_MP_FLOATS (const char *)"Multiple" #endif }; const uint_fast32_t nbFloatPrecisions = sizeof(floatPrecisionStr) / sizeof(const char *); int GetFloatPrecision(FloatPrecision *floatPrecision, const char *str) { int res = 0; size_t len = strlen(str); if (len > 255) { FractalNow_werror("Unknown float precision \'%s\'.\n", str); } char FPStr[256]; strcpy(FPStr, str); toLowerCase(FPStr); uint_fast32_t i; for (i = 0; i < nbFloatPrecisions; ++i) { if (strcmp(FPStr, floatPrecisionStr[i]) == 0) { *floatPrecision = (FloatPrecision)i; break; } } if (i == nbFloatPrecisions) { FractalNow_werror("Unknown float precision \'%s\'.\n", str); } end: return res; } #ifdef _ENABLE_MP_FLOATS int64_t fractalnow_mp_precision = DEFAULT_MP_PRECISION; int64_t GetMinMPFloatPrecision() { if (MPFR_PREC_MIN < INT64_MIN) { return INT64_MIN; } else { return (int64_t)MPFR_PREC_MIN; } } int64_t GetMaxMPFloatPrecision() { if (MPFR_PREC_MAX > INT64_MAX) { return INT64_MAX; } else { return (int64_t)MPFR_PREC_MAX; } } int64_t GetMPFloatPrecision() { return fractalnow_mp_precision; } void SetMPFloatPrecision(int64_t precision) { if (precision >= MPFR_PREC_MIN && precision <= MPFR_PREC_MAX) { fractalnow_mp_precision = precision; mpfr_set_default_prec((mpfr_prec_t)fractalnow_mp_precision); } } #endif fractalnow-0.8.2/command-line/include/command_line.h000664 001750 001750 00000005676 13175112471 022411 0ustar00mpegmpeg000000 000000 /* * command_line.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file command_line.h * \brief Header file related to command line parsing. * \author Marc Pegon */ #ifndef __COMMAND_LINE_H__ #define __COMMAND_LINE_H__ #include "anti_aliasing.h" #include "fractalnow.h" #include #ifdef __cplusplus extern "C" { #endif /** * \struct CommandLineArguments * \brief For storing command lines arguments. * * This structure is to store the arguments given on the command line. */ /** * \typedef CommandLineArguments * \brief Convenient typedef for struct CommandLineArguments. */ typedef struct CommandLineArguments { char *fractalConfigFileName; /*!< Fractal Config file name.*/ char *fractalFileName; /*!< Fractal file name.*/ char *renderingFileName; /*!< Rendering file name.*/ char *gradientFileName; /*!< Gradient file name.*/ char *dstFileName; /*!< Output image file name.*/ uint_fast32_t width; /*!< Width of output float table/image.*/ uint_fast32_t height; /*!< Height of output float table/image.*/ uint_fast32_t quadInterpolationSize; /*!< Maximum size of quadrilaterals for interpolation.*/ int nbThreads; /*!< Number of threads. Negative if not specified. */ double colorDissimilarityThreshold; /*!< Dissimilarity threshold for interpolation.*/ AntiAliasingMethod antiAliasingMethod; /*!< Anti-aliasing method.*/ double antiAliasingSize; /*!< Size for anti-aliasing (radius for blur, factor for oversampling and adaptive).*/ double adaptiveAAMThreshold; /*!< Threshold used when anti-aliasing method is adaptive.*/ FloatPrecision floatPrecision; /*!< Float precision.*/ #ifdef _ENABLE_MP_FLOATS int64_t MPFloatPrecision; /*!< Precision (value) of Multiple Precision floats.*/ #endif } CommandLineArguments; /** * \fn void ParseCommandLineArguments(CommandLineArguments *dst, int argc, char *argv[]) * \brief Parse arguments given on command line. * * \param dst Pointer to the (already allocated) structure in which to store the arguments. * \param argc Argc of the main function * \param argv Argv of the main function */ void ParseCommandLineArguments(CommandLineArguments *dst, int argc, char *argv[]); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/man/qfractalnow.1000664 001750 001750 00000006260 13175115345 016774 0ustar00mpegmpeg000000 000000 .TH "QFRACTALNOW" "1" "2012-07-11" "QFractalNow" "Fractal explorer/generator" .SH NAME qfractalnow \- Explore fractals and generate fractal images. .SH SYNOPSYS .B qfractalnow [OPTIONS] .SH DESCRIPTION QFractalNow is a graphical tool, based on Qt library, that allows users to explore fractals intuitively and generate pictures. .br It is multi-threaded and implements advanced algorithms and heuristics that make computation very fast compared to most existing free fractal generators. .br See FractalNow, a command-line tool to generate fractal images. .SH OPTIONS .TP .B \-h Print help. . .TP .B \-q Quiet mode, only errors are displayed. . .TP .B \-v Verbose mode. . .TP .B \-j Specify number of threads (see help for default value). . .TP .B \-c Specify configuration file, overriding default configuration. . .TP .B \-f Specify fractal file, overriding parameters from default configuration or configuration file. . .TP .B \-r Specify rendering file, overriding parameters from default configuration or configuration file. . .TP .B \-g Specify gradient file, overriding gradient from default configuration, configuration file, or rendering file. . .TP .B \-x Specify image width. . .TP .B \-y Specify image height. . .TP .B \-l Specify float type: .RS single Single precision. .br double Double precision. .br ldouble Long double precision. .br mp Multiple precision. .RE . .TP .B \-L Specify precision of Multiple Precision (MP) floats (see help for default value). . .TP .B \-a Specify anti-aliasing method: .RS none By default. .br blur Gaussian blur. .br oversampling Oversampling. .br adaptive Smart oversampling. .RE . .TP .B \-m Specify minimum size of adaptive anti-aliasing (see help for default value). .br Must be an integer strictly greater than 1. . .TP .B \-M Specify maximum size of adaptive anti-aliasing (see help for default value). .br Must be an integer strictly greater than 1 and MinAAMSize. . .TP .B \-n Anti-aliasing size iteration. .br Anti-aliasing size will increase by steps of AAMSizeIteration from MinAAMSize to MaxAAMSize. . .TP .B \-p Threshold for adaptive anti-aliasing (see help for default value). . .TP .B \-i Maximum size of quadrilaterals for linear interpolation. .RS Default is good for no visible loss of quality (see help for default value). .br 1 means no interpolation (all pixels are computed). .RE . .TP .B \-t Dissimilarity threshold for quad interpolation. .RS Default is good for no visible loss of quality (see help for default value). .br A quadrilateral that shows too dissimilar values at its corners will be computed, as opposed to interpolated. .RE .SH AUTHOR QFractalNow was written by Marc Pegon . .SH COPYRIGHT QFractalNow is licensed under the terms of the GNU Lesser General Public License, Version 3 or any later version published by the Free Software Foundation. .SH "SEE ALSO" FractalNow manual page. .br Documentation files describing configuration, fractal, rendering and gradient files formats. fractalnow-0.8.2/lib/include/fractal_iteration_count.h000664 001750 001750 00000012377 13175115345 023070 0ustar00mpegmpeg000000 000000 /* * fractal_iteration_count.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal_iteration_count.h * \brief Header file related to fractal iteration count. * \author Marc Pegon */ #ifndef __FRACTAL_ITERATION_COUNT_H__ #define __FRACTAL_ITERATION_COUNT_H__ #include "float_precision.h" #ifdef __cplusplus extern "C" { #endif /** * \enum e_IterationCount * \brief Possible iteration counts. * * There are different ways to "count" the number of iterations * when computing fractal :\n * it can be either simply the number of iterations itself (which * is discrete), or more advanced stuff like continuous or smooth * iteration count.\n */ /** * \typedef IterationCount * \brief Convenient typedef for enum e_IterationCount. */ typedef enum e_IterationCount { IC_DISCRETE = 0, /*res, data->n); /*********************************************************/ /**********************IC_CONTINUOUS**********************/ #define ENGINE_DECL_VAR_IC_CONTINUOUS(fprec) \ FLOATTYPE(fprec) escapeRadiusP_IC;\ FLOATTYPE(fprec) absZ_IC;\ FLOATTYPE(fprec) diff0_IC;\ FLOATTYPE(fprec) diff1_IC; #define ENGINE_INIT_VAR_IC_CONTINUOUS(fprec) \ initF(fprec, data->escapeRadiusP_IC);\ cabsF(fprec, data->escapeRadiusP_IC, data->fractalP);\ powF(fprec, data->escapeRadiusP_IC, data->escapeRadius, data->escapeRadiusP_IC);\ initF(fprec, data->absZ_IC);\ initF(fprec, data->diff0_IC);\ initF(fprec, data->diff1_IC); #define ENGINE_CLEAR_VAR_IC_CONTINUOUS(fprec) \ clearF(fprec, data->escapeRadiusP_IC);\ clearF(fprec, data->absZ_IC);\ clearF(fprec, data->diff0_IC);\ clearF(fprec, data->diff1_IC); #define COMPUTE_IC_CONTINUOUS(fprec) \ sqrtF(fprec, data->absZ_IC, data->normZ);\ subF(fprec, data->diff0_IC, data->escapeRadiusP_IC, data->escapeRadius);\ subF(fprec, data->diff1_IC, data->escapeRadiusP_IC, data->absZ_IC);\ divF(fprec, data->diff0_IC, data->diff1_IC, data->diff0_IC);\ add_uiF(fprec, data->res, data->diff0_IC, data->n); /*********************************************************/ /************************IC_SMOOTH************************/ #define ENGINE_DECL_VAR_IC_SMOOTH(fprec) \ FLOATTYPE(fprec) logAbsZ_IC;\ FLOATTYPE(fprec) logEscapeRadius_IC;\ FLOATTYPE(fprec) logAbsP_IC; #define ENGINE_INIT_VAR_IC_SMOOTH(fprec) \ initF(fprec, data->logAbsZ_IC);\ initF(fprec, data->logEscapeRadius_IC);\ logF(fprec, data->logEscapeRadius_IC, data->escapeRadius);\ initF(fprec, data->logAbsP_IC);\ cabsF(fprec, data->logAbsP_IC, data->fractalP);\ logF(fprec, data->logAbsP_IC, data->logAbsP_IC); #define ENGINE_CLEAR_VAR_IC_SMOOTH(fprec) \ clearF(fprec, data->logAbsZ_IC);\ clearF(fprec, data->logEscapeRadius_IC);\ clearF(fprec, data->logAbsP_IC); #define COMPUTE_IC_SMOOTH(fprec) \ logF(fprec, data->logAbsZ_IC, data->normZ);\ div_uiF(fprec, data->logAbsZ_IC, data->logAbsZ_IC, 2);\ divF(fprec, data->res, data->logEscapeRadius_IC, data->logAbsZ_IC);\ logF(fprec, data->res, data->res);\ divF(fprec, data->res, data->res, data->logAbsP_IC);\ add_uiF(fprec, data->res, data->res, data->n+1); /*********************************************************/ #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/lib/include/000775 001750 001750 00000000000 13175153661 016006 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/command-line/Makefile.configure000664 001750 001750 00000003312 13175115345 021574 0ustar00mpegmpeg000000 000000 BINDIR = bin FRACTALLIBDIR = ../lib SRCDIR = src INCLUDEDIR = include OBJDIR = objs TARGET = ${BINDIR}/${TARGET_NAME} DEPENDENCY_FILE=${OBJDIR}/makefile.dep CC = gcc LD = gcc CFLAGS = -std=c99 -pedantic -Wall -Wextra -D${SPINLOCK_DEFINE} ifdef BUILTIN_COMPLEX_DEFINE CFLAGS += -D${BUILTIN_COMPLEX_DEFINE} endif ifdef MP_FLOATS_DEFINE CFLAGS += -D${MP_FLOATS_DEFINE} endif ifdef DEBUG CFLAGS += -O0 -g -DDEBUG else CFLAGS += -O2 endif CFLAGS += -I${INCLUDEDIR} -I${FRACTALLIBDIR}/include LDFLAGS = ${STATIC_FLAG} -L${FRACTALLIBDIR}/bin -l${FRACTAL2D_LIB} ifeq ($(MP_FLOATS_DEFINE), _ENABLE_MP_FLOATS) LDFLAGS += -lmpc -lmpfr -lgmp endif LDFLAGS += -lm -lpthread OBJECTS = \ $(OBJDIR)/anti_aliasing.o \ $(OBJDIR)/command_line.o \ $(OBJDIR)/help.o \ $(OBJDIR)/main.o all : $(OBJDIR) ${BINDIR} ${DEPENDENCY_FILE} $(TARGET) ${DEPENDENCY_FILE}: $(OBJDIR) ${SRCDIR}/*.c ${INCLUDEDIR}/*.h $(call quiet-command,for i in ${SRCDIR}/*.c; do ${CC} ${CFLAGS} -MM "$${i}"; done | sed "s/\(^.*:\)/${OBJDIR}\/\1/" > $@," BUILDING DEPENDENCY DATABASE"); -include ${DEPENDENCY_FILE} $(TARGET): $(OBJECTS) $(call quiet-command, $(LD) -o $@ $^ $(LDFLAGS), " LD $@") $(OBJDIR): $(call quiet-command, mkdir -p $(OBJDIR),) $(BINDIR): $(call quiet-command, mkdir -p $(BINDIR),) $(OBJDIR)/%.o:${SRCDIR}/%.c ${CC} ${CFLAGS} -c $< -o $@ clean: $(call quiet-command, rm -f ${DEPENDENCY_FILE}, " CLEAN (DEPENDENCY DATABASE)") $(call quiet-command, rm -f $(OBJECTS) , " CLEAN (OBJECTS)") distclean: clean $(call quiet-command, rm -rf $(OBJDIR), " CLEAN (OBJDIR)") $(call quiet-command, rm -rf $(BINDIR), " CLEAN (BINDIR)") fractalnow-0.8.2/examples/config_files/000775 001750 001750 00000000000 13175115345 020057 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/gui/qfractalnow.pro.configure000664 001750 001750 00000003300 13175134344 021415 0ustar00mpegmpeg000000 000000 TEMPLATE = app TARGET = $${TARGET_NAME} RESOURCES = $${TARGET_NAME}.qrc RCC_DIR = rcc/ win32:RC_FILE = $${TARGET_NAME}.rc ICON = icons/icon.icns OBJECTS_DIR = objs/ MOC_DIR = mocs/ DESTDIR = bin/ FRACTALLIBPATH = ../lib DEPENDPATH += . include src INCLUDEPATH += . include $${FRACTALLIBPATH}/include LIBS += -L$${FRACTALLIBPATH}/bin -l$${FRACTAL2D_LIB} -lmpc -lmpfr -lgmp -lpthread -lm DEFINES += __STDC_LIMIT_MACROS __STDC_FORMAT_MACROS $${BUILTIN_COMPLEX_DEFINE} $${SPINLOCK_DEFINE} $${MP_FLOATS_DEFINE} $${LDOUBLE_FLOATS_DEFINE} QT += widgets concurrent QMAKE_LFLAGS += $${STATIC_FLAG} CONFIG += warn_on qt CONFIG -= debug_and_release !isEmpty(DEBUG) { DEFINES += DEBUG CONFIG -= release CONFIG += debug console } else { CONFIG -= debug CONFIG += release } # Input HEADERS += \ include/color_button.h \ include/command_line.h \ include/export_fractal_image_dialog.h \ include/fractal_config_widget.h \ include/fractal_explorer.h \ include/fractal_rendering_widget.h \ include/gradient_box.h \ include/gradient_dialog.h \ include/gradient_editor.h \ include/gradient_label.h \ include/help.h \ include/hoverpoints.h \ include/main_window.h \ include/main.h \ include/mpfr_spin_box.h \ include/shade_widget.h \ include/task_progress_dialog.h SOURCES += \ src/color_button.cpp \ src/command_line.cpp \ src/export_fractal_image_dialog.cpp \ src/fractal_explorer.cpp \ src/fractal_config_widget.cpp \ src/fractal_rendering_widget.cpp \ src/gradient_box.cpp \ src/gradient_dialog.cpp \ src/gradient_editor.cpp \ src/gradient_label.cpp \ src/help.cpp \ src/hoverpoints.cpp \ src/main_window.cpp \ src/main.cpp \ src/mpfr_spin_box.cpp \ src/shade_widget.cpp \ src/task_progress_dialog.cpp fractalnow-0.8.2/lib/src/uirectangle.c000664 001750 001750 00000007410 13175112471 017614 0ustar00mpegmpeg000000 000000 /* * rectangle.c -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "uirectangle.h" #include "misc.h" #include inline void InitUIRectangle(UIRectangle *rectangle, uint_fast32_t x1, uint_fast32_t y1, uint_fast32_t x2, uint_fast32_t y2) { rectangle->x1 = x1; rectangle->y1 = y1; rectangle->x2 = x2; rectangle->y2 = y2; } UIRectangle CopyUIRectangle(const UIRectangle *rectangle) { UIRectangle res; InitUIRectangle(&res, rectangle->x1, rectangle->y1, rectangle->x2, rectangle->y2); return res; } void CutUIRectangleMaxSize(UIRectangle src, uint_fast32_t size, UIRectangle **out, uint_fast32_t *out_size) { uint_fast32_t width = src.x2 - src.x1 + 1; uint_fast32_t height = src.y2 - src.y1 + 1; uint_fast32_t nb_x = width / size; uint_fast32_t nb_y = height / size; if (width % size > 0) { nb_x++; } if (height % size > 0) { nb_y++; } *out_size = nb_x*nb_y; *out = (UIRectangle *)safeMalloc("rectangles", (*out_size)*sizeof(UIRectangle)); UIRectangle *p_out = *out; uint_fast32_t y1 = src.y1; uint_fast32_t y2 = src.y1+size-1; for (; y1 <= src.y2; y1+=size, y2+=size) { y2 = (y2 > src.y2) ? src.y2 : y2; uint_fast32_t x1 = src.x1; uint_fast32_t x2 = src.x1+size-1; for (; x1 <= src.x2; x1+=size, x2+=size) { x2 = (x2 > src.x2) ? src.x2 : x2; p_out->x1 = x1; p_out->x2 = x2; p_out->y1 = y1; p_out->y2 = y2; ++p_out; } } } int CutUIRectangleInHalf(UIRectangle rectangle, UIRectangle *out1, UIRectangle *out2) { uint_fast32_t width = rectangle.x2 - rectangle.x1; uint_fast32_t height = rectangle.y2 - rectangle.y1; if (width == 0 && height == 0) { return 1; } if (width >= height) { width /= 2; InitUIRectangle(out1, rectangle.x1, rectangle.y1, rectangle.x1 + width, rectangle.y2); InitUIRectangle(out2, rectangle.x1 + width + 1, rectangle.y1, rectangle.x2, rectangle.y2); } else { height /= 2; InitUIRectangle(out1, rectangle.x1, rectangle.y1, rectangle.x2, rectangle.y1 + height); InitUIRectangle(out2, rectangle.x1, rectangle.y1 + height + 1, rectangle.x2, rectangle.y2); } return 0; } int CutUIRectangleInN(UIRectangle rectangle, uint_fast32_t N, UIRectangle *out) { uint_fast32_t width = rectangle.x2 + 1 - rectangle.x1; uint_fast32_t height = rectangle.y2 + 1 - rectangle.y1; if (width*height < N) { return 1; } uint_fast32_t nbRectangles = 1; uint_fast32_t tmpNbRectangles; InitUIRectangle(&out[0], rectangle.x1, rectangle.y1, rectangle.x2, rectangle.y2); while (nbRectangles < N) { tmpNbRectangles = nbRectangles; for (uint_fast32_t i = 0; i < tmpNbRectangles; i++) { if (CutUIRectangleInHalf(out[i], &out[i], &out[nbRectangles])) { /* This particular rectangle could not be in half. * Assuming that the initial rectangle could be cut in N parts, * we know that there still exists a rectangle that can be cut * in half (until we have reached N rectangles). * Just skip this one and try the next. */ continue; } else { nbRectangles++; } if (nbRectangles == N) { break; } } } return 0; } fractalnow-0.8.2/gui/src/gradient_label.cpp000664 001750 001750 00000002734 13175112471 020630 0ustar00mpegmpeg000000 000000 /* * gradient_label.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "gradient_label.h" #include GradientLabel::GradientLabel(QWidget *parent) : QLabel(parent) { gradientStops << QGradientStop(0, QColor::fromRgb(0x0)); gradientStops << QGradientStop(1, QColor::fromRgb(0xFFFFFF)); } void GradientLabel::setGradientStops(const QGradientStops &gradientStops) { this->gradientStops = gradientStops; update(); } void GradientLabel::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QPainter painter(this); QLinearGradient qGradient(rect().topLeft(), rect().topRight()); qGradient.setStops(gradientStops); painter.setBrush(qGradient); painter.setPen(Qt::NoPen); painter.drawRect(rect()); } fractalnow-0.8.2/gui/qfractalnow.rc000664 001750 001750 00000000055 13175134320 017237 0ustar00mpegmpeg000000 000000 IDI_ICON1 ICON DISCARDABLE "icons/icon.ico" fractalnow-0.8.2/gui/src/fractal_rendering_widget.cpp000664 001750 001750 00000015623 13175112471 022711 0ustar00mpegmpeg000000 000000 /* * fractal_rendering_widget.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "fractal_rendering_widget.h" #include #include #include #include FractalRenderingWidget::FractalRenderingWidget(const RenderingParameters &render) : QWidget() { coloringMethodComboBox = new QComboBox; for (uint_fast32_t i = 0; i < nbColoringMethods; ++i) { coloringMethodComboBox->addItem(coloringMethodDescStr[i]); } coloringMethodComboBox->setCurrentIndex((int)render.coloringMethod); iterationCountComboBox = new QComboBox; for (uint_fast32_t i = 0; i < nbIterationCounts; ++i) { iterationCountComboBox->addItem(iterationCountDescStr[i]); } iterationCountComboBox->setCurrentIndex((int)render.iterationCount); addendFunctionComboBox = new QComboBox; for (uint_fast32_t i = 0; i < nbAddendFunctions; ++i) { addendFunctionComboBox->addItem(addendFunctionDescStr[i]); } addendFunctionComboBox->setCurrentIndex((int)render.addendFunction); stripeDensitySpinBox = new QSpinBox; stripeDensitySpinBox->setRange(1, std::numeric_limits::max()); stripeDensitySpinBox->setValue((int)render.stripeDensity); stripeDensitySpinBox->setAccelerated(true); interpolationMethodComboBox = new QComboBox; for (uint_fast32_t i = 0; i < nbInterpolationMethods; ++i) { interpolationMethodComboBox->addItem(interpolationMethodDescStr[i]); } interpolationMethodComboBox->setCurrentIndex((int)render.interpolationMethod); transferFunctionComboBox = new QComboBox; for (uint_fast32_t i = 0; i < nbTransferFunctions; ++i) { transferFunctionComboBox->addItem(transferFunctionDescStr[i]); } transferFunctionComboBox->setCurrentIndex((int)render.transferFunction); spaceColorButton = new ColorButton; spaceColorButton->setCurrentColor(QColor(render.spaceColor.r, render.spaceColor.g, render.spaceColor.b)); colorScalingSpinBox = new QDoubleSpinBox; colorScalingSpinBox->setDecimals(8); colorScalingSpinBox->setRange(0, std::numeric_limits::max()); colorScalingSpinBox->setValue(render.multiplier); colorScalingSpinBox->setAccelerated(true); colorOffsetSpinBox = new QDoubleSpinBox; colorOffsetSpinBox->setDecimals(6); colorOffsetSpinBox->setRange(0, 1); colorOffsetSpinBox->setWrapping(true); colorOffsetSpinBox->setSingleStep(0.01); colorOffsetSpinBox->setValue(render.offset); colorOffsetSpinBox->setAccelerated(true); gradientBox = new GradientBox(render.gradient); QFormLayout *formLayout = new QFormLayout; formLayout->addRow(tr("Coloring method:"), coloringMethodComboBox); formLayout->addRow(tr("Iteration count:"), iterationCountComboBox); formLayout->addRow(tr("Addend function:"), addendFunctionComboBox); formLayout->addRow(tr("Stripe density:"), stripeDensitySpinBox); formLayout->addRow(tr("Interpolation method:"), interpolationMethodComboBox); formLayout->addRow(tr("Transfer function:"), transferFunctionComboBox); formLayout->addRow(tr("Color scaling:"), colorScalingSpinBox); formLayout->addRow(tr("Color offset:"), colorOffsetSpinBox); formLayout->addRow(tr("Space color:"), spaceColorButton); QVBoxLayout *vBoxLayout = new QVBoxLayout; vBoxLayout->addLayout(formLayout); vBoxLayout->addWidget(new QLabel(tr("Gradient:"))); vBoxLayout->addWidget(gradientBox); vBoxLayout->addStretch(1); this->setLayout(vBoxLayout); updateBoxesEnabledValue(); updateColorScalingSingleStep(); connect(coloringMethodComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateBoxesEnabledValue())); connect(addendFunctionComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateBoxesEnabledValue())); connect(colorScalingSpinBox, SIGNAL(valueChanged(double)), this, SLOT(updateColorScalingSingleStep())); } void FractalRenderingWidget::blockBoxesSignals(bool block) { iterationCountComboBox->blockSignals(block); coloringMethodComboBox->blockSignals(block); addendFunctionComboBox->blockSignals(block); stripeDensitySpinBox->blockSignals(block); interpolationMethodComboBox->blockSignals(block); transferFunctionComboBox->blockSignals(block); colorScalingSpinBox->blockSignals(block); colorOffsetSpinBox->blockSignals(block); spaceColorButton->blockSignals(block); gradientBox->blockSignals(block); } void FractalRenderingWidget::updateBoxesValues(const RenderingParameters &render) { blockBoxesSignals(true); iterationCountComboBox->setCurrentIndex((int)render.iterationCount); coloringMethodComboBox->setCurrentIndex((int)render.coloringMethod); addendFunctionComboBox->setCurrentIndex((int)render.addendFunction); stripeDensitySpinBox->setValue(render.stripeDensity); interpolationMethodComboBox->setCurrentIndex((int)render.interpolationMethod); transferFunctionComboBox->setCurrentIndex((int)render.transferFunction); colorScalingSpinBox->setValue(render.multiplier); colorOffsetSpinBox->setValue(render.offset); spaceColorButton->setCurrentColor(QColor(render.spaceColor.r, render.spaceColor.g, render.spaceColor.b)); gradientBox->setGradient(render.gradient); updateColorScalingSingleStep(); updateBoxesEnabledValue(); blockBoxesSignals(false); } void FractalRenderingWidget::updateBoxesEnabledValue() { ColoringMethod coloringMethod = (ColoringMethod)coloringMethodComboBox->currentIndex(); AddendFunction addendFunction = (AddendFunction)addendFunctionComboBox->currentIndex(); switch (coloringMethod) { case CM_ITERATIONCOUNT: iterationCountComboBox->setEnabled(true); addendFunctionComboBox->setEnabled(false); stripeDensitySpinBox->setEnabled(false); interpolationMethodComboBox->setEnabled(false); break; case CM_AVERAGECOLORING: iterationCountComboBox->setEnabled(false); addendFunctionComboBox->setEnabled(true); stripeDensitySpinBox->setEnabled(addendFunction == AF_STRIPE); interpolationMethodComboBox->setEnabled(true); break; default: iterationCountComboBox->setEnabled(true); addendFunctionComboBox->setEnabled(true); stripeDensitySpinBox->setEnabled(true); interpolationMethodComboBox->setEnabled(true); break; } } void FractalRenderingWidget::updateColorScalingSingleStep() { double colorScaling = colorScalingSpinBox->value(); colorScalingSpinBox->setSingleStep(colorScaling / 10); } void FractalRenderingWidget::editGradient() { gradientBox->openGradientDialog(); } fractalnow-0.8.2/command-line/src/command_line.c000664 001750 001750 00000020604 13175112471 021534 0ustar00mpegmpeg000000 000000 /* * command_line.c -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "command_line.h" #include "help.h" #include "fractalnow.h" #include #include #include int FileExists(const char *fileName) { FILE *file; int res = 0; if ((file = fopen(fileName,"r")) != NULL) { res = 1; fclose(file); } return res; } void ParseCommandLineArguments(CommandLineArguments *dst, int argc, char *argv[]) { FractalNow_traceLevel = T_NORMAL; FractalNow_debug = 0; int help = 0; dst->quadInterpolationSize = DEFAULT_QUAD_INTERPOLATION_SIZE; dst->colorDissimilarityThreshold = DEFAULT_COLOR_DISSIMILARITY_THRESHOLD; int64_t tmp; double unused; dst->fractalConfigFileName = NULL; dst->fractalFileName = NULL; dst->renderingFileName = NULL; dst->gradientFileName = NULL; dst->dstFileName = NULL; dst->antiAliasingMethod = AAM_NONE; dst->antiAliasingSize = -1; dst->adaptiveAAMThreshold = -1; dst->nbThreads = -1; dst->floatPrecision = FP_DOUBLE; #ifdef _ENABLE_MP_FLOATS dst->MPFloatPrecision = DEFAULT_MP_PRECISION; #endif int widthSpecified = 0, heightSpecified = 0; dst->width = 0; dst->height = 0; int o; while ((o = getopt(argc, argv, "hqvda:c:f:g:i:j:l:L:o:p:r:s:t:x:y:")) != -1) { switch (o) { case 'h': help = 1; break; case 'q': if (FractalNow_traceLevel == T_VERBOSE) { invalid_use_error("-q and -v are mutually exclusive.\n"); } FractalNow_traceLevel = T_QUIET; break; case 'v': if (FractalNow_traceLevel == T_QUIET) { invalid_use_error("-q and -v are mutually exclusive.\n"); } FractalNow_traceLevel = T_VERBOSE; break; case 'd': #ifndef DEBUG FractalNow_message(stdout, T_QUIET, "Debug unavailable: FractalNow was not built in \ debug mode.\n"); #else FractalNow_debug = 1; #endif break; case 'a': dst->antiAliasingMethod = GetAAM(optarg); break; case 'c': dst->fractalConfigFileName = optarg; break; case 'f': dst->fractalFileName = optarg; break; case 'r': dst->renderingFileName = optarg; break; case 'g': dst->gradientFileName = optarg; break; case 'l': if (GetFloatPrecision(&dst->floatPrecision, optarg)) { invalid_use_error("\n"); } break; #ifdef _ENABLE_MP_FLOATS case 'L': if (sscanf(optarg, "%"SCNd64, &tmp) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (tmp < GetMinMPFloatPrecision() || tmp > GetMaxMPFloatPrecision()) { invalid_use_error("MP floats precision must be between %"PRId64 " and %"PRId64".\n", GetMinMPFloatPrecision(), GetMaxMPFloatPrecision()); } else { dst->MPFloatPrecision = (mpfr_prec_t)tmp; } break; #endif case 'i': if (sscanf(optarg, "%"SCNd64, &tmp) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (tmp <= 0) { invalid_use_error("Quad interpolation size must be positive.\n"); } else { dst->quadInterpolationSize = (uint_fast32_t)tmp; } break; case 'j': if (sscanf(optarg, "%d", &dst->nbThreads) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (dst->nbThreads <= 0) { invalid_use_error("Number of threads must be positive.\n"); } break; case 'o': dst->dstFileName = optarg; break; case 'p': if (sscanf(optarg, "%lf", &dst->adaptiveAAMThreshold) < 1) { invalid_use_error("Command-line argument \'%s\' is not a floating-point number.\n", optarg); } if (dst->adaptiveAAMThreshold < 0.) { invalid_use_error("Adaptive anti-aliasing threshold must be >= 0.\n"); } break; case 's': if (sscanf(optarg, "%lf", &dst->antiAliasingSize) < 1) { invalid_use_error("Command-line argument \'%s\' is not a floating-point number.\n", optarg); } break; case 't': if (sscanf(optarg, "%lf", &dst->colorDissimilarityThreshold) < 1) { invalid_use_error("Command-line argument \'%s\' is not a floating-point number.\n", optarg); } if (dst->colorDissimilarityThreshold < 0.) { invalid_use_error("Quad dissimilarity threshold must be between >= 0.\n"); } break; case 'x': if (sscanf(optarg, "%"SCNd64, &tmp) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (tmp < 2) { invalid_use_error("Output image width must be >= 2.\n"); } else { dst->width = (uint_fast32_t)tmp; widthSpecified = 1; } break; case 'y': if (sscanf(optarg, "%"SCNd64, &tmp) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (tmp < 2) { invalid_use_error("Output image height must be >= 2.\n"); } else { dst->height = (uint_fast32_t)tmp; heightSpecified = 1; } break; default: DisplayHelp(); exit(EXIT_FAILURE); break; } } if (argv[optind] != NULL) { invalid_use_error("Remaining argument on command line : '%s'.\n", argv[optind]); } if (help) { DisplayHelp(); exit(EXIT_SUCCESS); } if (dst->fractalConfigFileName == NULL) { if (dst->fractalFileName == NULL) { invalid_use_error("No configuration or fractal file specified.\n"); } if (dst->renderingFileName == NULL) { invalid_use_error("No configuration or rendering file specified.\n"); } } if (dst->dstFileName == NULL) { invalid_use_error("No output file specified.\n"); } if (!widthSpecified && !heightSpecified) { invalid_use_error("At least width or height must be specified.\n"); } switch (dst->antiAliasingMethod) { case AAM_NONE: if (dst->antiAliasingSize != -1) { invalid_use_error("No size parameter ('-s') should be specified when \ anti-aliasing is disabled.\n"); } break; case AAM_GAUSSIANBLUR: if (dst->antiAliasingSize == -1) { invalid_use_error("No size parameter ('-s') specified for blur.\n"); } if (dst->antiAliasingSize <= 0) { invalid_use_error("Size parameter ('-s') for gaussian blur must be > 0.\n"); } if (dst->adaptiveAAMThreshold != -1) { invalid_use_error("No adaptive anti-aliasing threshold ('-p') should be \ specified when anti-aliasing method is blur.\n"); } break; case AAM_OVERSAMPLING: if (dst->antiAliasingSize == -1) { invalid_use_error("No size parameter ('-s') specified for oversampling.\n"); } if (dst->antiAliasingSize <= 1.) { invalid_use_error("Size parameter ('-s') for oversampling must be > 1.\n"); } if (dst->adaptiveAAMThreshold != -1) { invalid_use_error("No adaptive anti-aliasing threshold ('-p') should be \ specified when anti-aliasing method is oversampling.\n"); } break; case AAM_ADAPTIVE: if (dst->antiAliasingSize == -1) { invalid_use_error("No size parameter ('-s') specified for adaptive \ anti-aliasing.\n"); } if (modf(dst->antiAliasingSize, &unused) != 0) { invalid_use_error("Size parameter ('-s') for adaptive anti-aliasing \ should be an integer.\n"); } if (dst->antiAliasingSize <= 1.) { invalid_use_error("Size parameter ('-s') for adaptive anti-aliasing \ must be > 1.\n"); } if (dst->adaptiveAAMThreshold == -1) { dst->adaptiveAAMThreshold = DEFAULT_ADAPTIVE_AAM_THRESHOLD; } break; default: invalid_use_error("Unknown anti-aliasing method.\n"); break; } if (dst->fractalConfigFileName != NULL && !FileExists(dst->fractalConfigFileName)) { FractalNow_existence_error(dst->fractalConfigFileName); } if (dst->fractalFileName != NULL && !FileExists(dst->fractalFileName)) { FractalNow_existence_error(dst->fractalFileName); } if (dst->renderingFileName != NULL && !FileExists(dst->renderingFileName)) { FractalNow_existence_error(dst->renderingFileName); } if (dst->gradientFileName != NULL && !FileExists(dst->gradientFileName)) { FractalNow_existence_error(dst->gradientFileName); } } fractalnow-0.8.2/lib/include/color.h000664 001750 001750 00000015616 13175115345 017303 0ustar00mpegmpeg000000 000000 /* * color.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file color.h * \brief Header file related to colors. * \author Marc Pegon */ #ifndef __COLOR_H__ #define __COLOR_H__ #include #ifdef __cplusplus extern "C" { #endif /** * \def GET_R8(x) * \brief Get red component of uint32_t color. */ #define GET_R8(x) ((x >> 16) & 0xFF) /** * \def GET_G8(x) * \brief Get green component of uint32_t color. */ #define GET_G8(x) ((x >> 8) & 0xFF) /** * \def GET_B8(x) * \brief Get blue component of uint32_t color. */ #define GET_B8(x) (x & 0xFF) /** * \def RGB8_TO_UINT32(r,g,b) * \brief Create uint32_t color from 8-bits red, green, and blue components. * * alpha is set to 0xFF by default. */ #define RGB8_TO_UINT32(r,g,b) (0xFF000000+((uint32_t)(r)<<16)+((uint32_t)(g)<<8)+(uint32_t)b) /** * \def ARGB8_TO_UINT32(a,r,g,b) * \brief Create uint32_t color from 8-bits alpha, red, green, and blue components. */ #define ARGB8_TO_UINT32(a,r,g,b) (((uint32_t)(a)<<24)+((uint32_t)(r)<<16)+((uint32_t)(g)<<8)+(uint32_t)b) /** * \def GET_R16(x) * \brief Get red component of uint64_t color. */ #define GET_R16(x) ((x >> 32) & 0xFFFF) /** * \def GET_G16(x) * \brief Get green component of uint64_t color. */ #define GET_G16(x) ((x >> 16) & 0xFFFF) /** * \def GET_B16(x) * \brief Get blue component of uint64_t color. */ #define GET_B16(x) (x & 0xFFFF) /** * \def RGB16_TO_UINT64(r,g,b) * \brief Create uint64_t color from 16-bits red, green, and blue components. * * alpha is set to 0xFFFF by default. */ #define RGB16_TO_UINT64(r,g,b) (0xFFFF000000000000+((uint64_t)(r)<<32)+((uint64_t)(g)<<16)+(uint64_t)b) /** * \def ARGB16_TO_UINT64(r,g,b) * \brief Create uint64_t color from 16-bits alpha, red, green, and blue components. */ #define ARGB16_TO_UINT64(a,r,g,b) (((uint64_t)(a)<<48)+((uint64_t)(r)<<32)+((uint64_t)(g)<<16)+(uint64_t)b) /** * \struct Color * \brief Simple RGB color structure. */ /** * \typedef Color * \brief Convenient typedef for struct Color. */ typedef struct Color { uint_fast8_t bytesPerComponent; /*!< Either 1 (RGB8) or 2 (RGB16).*/ uint_fast16_t r; /*!< Red component.*/ uint_fast16_t g; /*!< Green component.*/ uint_fast16_t b; /*!< Blue component.*/ } Color; /** * \fn Color ColorFromRGB(uint8_t bytesPerComponent, uint16_t r, uint16_t g, uint16_t b) * \brief Create color from RGB values. * * bytesPerComponent must be 1 or 2. * * \param bytesPerComponent Bytes per component. * \param r Red value. * \param g Green value. * \param b Blue value. * \return Corresponding color structure. */ Color ColorFromRGB(uint8_t bytesPerComponent, uint16_t r, uint16_t g, uint16_t b); /** * \fn Color ColorFromUint32(uint32_t color) * \brief Convert a uint32_t color to Color structure. * * Creates a RGB8 Color structure. * alpha component (most significant 8 bits) is ignored. * * \param color Color to convert. * \return Converted color. */ Color ColorFromUint32(uint32_t color); /** * \fn Color ColorFromUint64(uint64_t color) * \brief Convert a uint64_t color to Color structure. * * Creates a RGB16 Color structure. * alpha component (most significant 16 bits) is ignored. * * \param color Color to convert. * \return Converted color. */ Color ColorFromUint64(uint64_t color); /** * \fn Color Color16(Color color) * \brief Convert color to 16 bits color. * * Simple copy if color bytes per component is already 2. * * \param color Color to be converted. * \return 16 bits color. */ Color Color16(Color color); /** * \fn Color Color8(Color color) * \brief Convert color to 8 bits color. * * Simple copy if color bytes per component is already 1. * * \param color Color to be converted. * \return 8 bits color. */ Color Color8(Color color); /** * \fn int CompareColors(const Color color1, const Color color2) * \brief Compare two colors. * * \param color1 First color. * \param color2 Second color. * \return 0 if colors are the same, 1 otherwise. */ int CompareColors(const Color color1, const Color color2); /** * \fn Color MixColors(Color C1, double weight1, Color C2, double weight2) * \brief Mix two weighted colors. * * Both colors must have same number of bytes per component * (undefined behaviour otherwise). * * \param C1 First Color. * \param weight1 Weight given to first color for mixing. * \param C2 Second Color. * \param weight2 Weight given to second color for mixing. * \return Result of the mixing of colors C1 and C2 according to given weights. */ Color MixColors(Color C1, double weight1, Color C2, double weight2); /** * \fn double ColorManhattanDistance(Color C1, Color C2) * \brief Compute manhattan distance between two colors. * * Distance is normalized (i.e. between 0 and 1).\n * Both colors must have same number of bytes per component * (undefined behaviour otherwise). * * \param C1 First color. * \param C2 Second color. * \return Manhattan distance between colors C1 and C2. */ double ColorManhattanDistance(Color C1, Color C2); /** * \fn double QuadAvgDissimilarity(const Color C[4]) * \brief Compute average dissimilarity of a quadrilateral given its corner colors. * * Result is normalized (between 0 and 1).\n * Colors must have same number of bytes per component * (undefined behaviour otherwise). * * \param C Point to colors at the four corners. * \return Quadrilateral average anhattan dissimilarity. */ double QuadAvgDissimilarity(const Color C[4]); /** * \fn Color QuadLinearInterpolation(const Color C[4], double x, double y) * \brief Interpolate linearly some color of a quadrilateral. * * Interpolate color at point (x,y) according to its corner colors.\n * Coordinates x and y are relative (undefined behaviour otherwise) : * (0,0 is the top left corner, (1,0) the top right, etc...\n * Colors must have same number of bytes per component * (undefined behaviour otherwise). * * \param C Quadrilateral corner colors. * \param x X (relative) coordinate of quad point to interpolate. * \param y Y (relative) coordinate of quad point to interpolate. * \return Linearly interpolated color at point (x,y) of quadrilateral. */ Color QuadLinearInterpolation(const Color C[4], double x, double y); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/doc/rendering_file_syntax.txt000664 001750 001750 00000007002 13175112471 021476 0ustar00mpegmpeg000000 000000 Rendering files contain all parameters necessary to render a fractal file. Remark: The end of a rendering file is merely the body of a gradient file. Rendering file syntax: RENDERING_FILE_FORMAT BYTES_PER_COMPONENT SPACE_COLOR COLOR_SCALING COLOR_OFFSET NB_TRANSITIONS COLORING_METHOD [ITERATION_COUNT | [ADDEND_FUNCTION [STRIPE_DENSITY] INTERPOLATION_METHOD]] Pos1 Color1 ... PosN ColorN Text characters can be upper-case or lower-case. Arguments separators can be tabs, blank spaces, carriage return. RENDERING_FILE_FORMAT should be R073, which is the format described in this document. Other format values (of older versions) may still be supported though. BYTES_PER_COMPONENT specifies the number of bytes per component used for colors. It can be : - 1 for RGB8 (8 bits per component) - 2 for RGB16 (16 bits per component) SPACE_COLOR specifies the color of points inside fractal. COLORING_METHOD can be : - ITERATIONCOUNT : the value returned by the iteration count is directly used - AVERAGECOLORING : average sum(s) is/are computed using the specified addend function ITERATION_COUNT is only needed for ITERATIONCOUNT coloring method, and should *not* be specified for AVERAGECOLORING coloring method. Symmetrically, ADDEND_FUNCTION and INTERPOLATION_METHOD are only needed for AVERAGECOLORING coloring method, and should *not* be specified for ITERATIONCOUNT coloring method. ITERATION_COUNT can be : - DISCRETE for discrete iteration count (simply the number of iterations). - CONTINUOUS for continuous iteration count - SMOOTH for smooth iteration count ADDEND_FUNCION can be : - TRIANGLEINEQUALITY - CURVATURE - STRIPE STRIPE_DENSITY is a positive integer used only for STRIPE addend function. It should not be specified for other addend functions. INTERPOLATION_METHOD can be : - NONE : only 1 average sum is computed and is directly used - LINEAR : 2 average sums are computed and interpolated linearly using smooth iteration count to produce one value - SPLINE : 4 average sums are computed and interpolated with polynomials using smooth iteration count to produce one value TRANSFER_FUNCTION specifies the transfer function to apply to the (nearly) final value, in order to map it better to the gradient. It can be : - LOG for logarithm (base e) - SQUAREROOT for square root - CUBEROOT for cube root - IDENTITY for identity function (value unchanged) - SQUARE for square - CUBE for cube - EXP for exponential COLOR_SCALING specifies a (floating point) multiplicand to be applied after transfer function, again to fit better to the gradient. COLOR_OFFSET specifies a (floating point) addend to be applied after multiplicand, again, to fit better to the gradient. It must be between 0 and 1. POSi : position of COLORi in gradient (between 0 and 1). First position must be 0, and last position must be 1. Positions must be strictly increasing. COLORi : colors composing gradient. Gradient must be made of at least 2 colors. Colors must be specified as hexadecimal numbers. Red, green, and blue are respectively the 1st, 2nd and 3rd component. Some RGB8 color examples : - 0x0 for black - 0xFF for blue - 0xFF00 for green - 0xFF0000 for red - 0xFFFFFF for white Some RGB16 color examples : - 0x0 for black - 0xFFFF for blue - 0xFFFF0000 for green - 0xFFFF00000000 for red - 0xFFFFFFFFFFFF for white In order for the gradient not to be discontinuous, the first and last color should be the same, for example 0x0 0xFFFFFF 0x0 for a black and white continuous gradient. Acceptable floating numbers are for example : 2.567 4.146E-5 8.26e2 fractalnow-0.8.2/examples/config_files/config03.config000664 001750 001750 00000000234 13175112471 022652 0ustar00mpegmpeg000000 000000 c075 mandelbrot -0.87591 0.25464 0.53184 0.53184 16 1000 1 0x0 iterationcount smooth identity 0.01 0 0 0xff 0.25 0xffffff 0.5 0xffff00 0.75 0xff0000 1 0xff fractalnow-0.8.2/command-line/src/anti_aliasing.c000664 001750 001750 00000003464 13175112471 021716 0ustar00mpegmpeg000000 000000 /* * anti_aliasing.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "anti_aliasing.h" #include "fractalnow.h" #include #include const char *AntiAliasingMethodStr[] = { (char *)"none", (char *)"blur", (char *)"oversampling", (char *)"adaptive" }; const char *AntiAliasingMethodDescStr[] = { (char *)"None", (char *)"Gaussian blur", (char *)"Oversampling", (char *)"Adaptive" }; uint_fast32_t nbAntiAliasingMethods = sizeof(AntiAliasingMethodStr) / sizeof(char *); AntiAliasingMethod GetAAM(const char *str) { int len = strlen(str); if (len > 255) { FractalNow_error("Unknown anti-aliasing method \'%s\'.\n", str); } char AAMStr[256]; strcpy(AAMStr, str); toLowerCase(AAMStr); AntiAliasingMethod res = (AntiAliasingMethod)0; uint_fast32_t i; for (i = 0; i < nbAntiAliasingMethods; ++i) { if (strcmp(AAMStr, AntiAliasingMethodStr[i]) == 0) { res = (AntiAliasingMethod)i; break; } } if (i == nbAntiAliasingMethods) { FractalNow_error("Unknown anti-aliasing method \'%s\'.\n", str); } return res; } fractalnow-0.8.2/gui/include/shade_widget.h000664 001750 001750 00000003054 13175112471 020620 0ustar00mpegmpeg000000 000000 /**************************************************************************** ** ** This file is based on some files of the demonstration applications of the ** Qt Toolkit. ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Modified to be used as a part of FractalNow: ** Copyright (c) 2012 Marc Pegon ** ** This file can be distributed and/or modified under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation. ** You should have received a copy of the GNU General Public License ** along with this file; if not, write to the Free Software Foundation, Inc., ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ** ****************************************************************************/ #ifndef __SHADE_WIDGET_H__ #define __SHADE_WIDGET_H__ #include "hoverpoints.h" class ShadeWidget : public QWidget { Q_OBJECT public: enum ShadeType { RedShade, GreenShade, BlueShade, ARGBShade }; ShadeWidget(ShadeType type, QWidget *parent = 0); void setGradientStops(const QGradientStops &stops); void paintEvent(QPaintEvent *e); QSize sizeHint() const { return QSize(150, 40); } QPolygonF points() const; HoverPoints *hoverPoints() const { return m_hoverPoints; } uint colorAt(int x); signals: void colorsChanged(); private: void generateShade(); ShadeType m_shade_type; HoverPoints *m_hoverPoints; QLinearGradient m_alpha_gradient; QImage m_shade; }; #endif fractalnow-0.8.2/gui/icons/icon.svg000664 001750 001750 00007562420 13175112471 017177 0ustar00mpegmpeg000000 000000 fractalnow-0.8.2/examples/config_files/config21.config000664 001750 001750 00000000650 13175115345 022657 0ustar00mpegmpeg000000 000000 c075 mandelbrot -0.743643925055 0.131825905901 1.84674112479512E-05 1.47739289983609E-05 1E+57 7500 1 0x0 averagecoloring curvature spline square 0.77352474 0.22 0 0x0 0.05 0x271108 0.1 0xaf4f2a 0.15 0xf7aa62 0.2 0xf9ecaf 0.25 0xe4fee2 0.3 0xb1edf9 0.35 0x6db7fa 0.4 0x2c52b4 0.45 0xb1430 0.5 0x0 0.55 0x6200e 0.6 0x27a74a 0.65 0x60f6a8 0.7 0xabfaea 0.75 0xdfe6fe 0.8 0xf9b4ef 0.85 0xf96ab4 0.9 0xbb2f58 0.95 0x270811 1 0x0 fractalnow-0.8.2/lib/src/fractal_config.c000664 001750 001750 00000017602 13175112471 020257 0ustar00mpegmpeg000000 000000 /* * fractal_config.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "fractal_config.h" #include "file_io.h" #include "fractal.h" #include "fractal_rendering_parameters.h" #include "misc.h" #include const char *fractalConfigFormatStr[] = { (const char *)"c075" }; const uint_fast32_t nbFractalConfigFormats = sizeof(fractalConfigFormatStr) / sizeof(const char *); int ReadFractalConfigFileV075(FractalConfig *fractalConfig, const char *fileName, FILE *file); typedef int (*ReadFractalConfigFileFunction)(FractalConfig *fractalConfig, const char *fileName, FILE *file); const ReadFractalConfigFileFunction readFractalConfigFileFunction[] = { ReadFractalConfigFileV075 }; int WriteFractalConfigFileV075(const FractalConfig *fractalConfig, const char *fileName, FILE *file); typedef int (*WriteFractalConfigFileFunction)(const FractalConfig *fractalConfig, const char *fileName, FILE *file); const WriteFractalConfigFileFunction writeFractalConfigFileFunction[] = { WriteFractalConfigFileV075 }; inline void InitFractalConfig(FractalConfig *config, Fractal fractal, RenderingParameters render) { config->fractal = fractal; config->render = render; } FractalConfig CopyFractalConfig(const FractalConfig *config) { FractalConfig res; InitFractalConfig(&res, CopyFractal(&config->fractal), CopyRenderingParameters(&config->render)); return res; } void ResetFractal(FractalConfig *config, Fractal fractal) { FreeFractal(config->fractal); config->fractal = CopyFractal(&fractal); } void ResetRenderingParameters(FractalConfig *config, RenderingParameters param) { FreeRenderingParameters(config->render); config->render = CopyRenderingParameters(¶m); } int ReadFractalConfigFileV075(FractalConfig *fractalConfig, const char *fileName, FILE *file) { int res = 0; const char fractalFormat[] = "f075"; const char renderingFormat[] = "r075"; res |= ReadFractalFileBody(&fractalConfig->fractal, fileName, file, fractalFormat); if (res) { FractalNow_werror("Failed to read fractal from fractal configuration file.\n"); } res |= ReadRenderingFileBody(&fractalConfig->render, fileName, file, renderingFormat); if (res) { FractalNow_werror("Failed to read rendering parameters from fractal \ configuration file.\n"); } end: return res; } ReadFractalConfigFileFunction GetReadFractalConfigFileFunction(const char *format) { if (strlen(format) != 4) { return NULL; } ReadFractalConfigFileFunction readFractalConfigFile = NULL; char formatStr[5]; strcpy(formatStr, format); toLowerCase(formatStr); uint_fast32_t i; for (i = 0; i < nbFractalConfigFormats; ++i) { if (strcmp(formatStr, fractalConfigFormatStr[i]) == 0) { readFractalConfigFile = readFractalConfigFileFunction[i]; break; } } return readFractalConfigFile; } int isSupportedFractalConfigFile(const char *fileName) { int res = 0; FILE *file; file=fopen(fileName,"r"); if (!file) { FractalNow_open_werror(fileName); } char formatStr[256]; if (readString(file, formatStr) < 1) { res = 1; } else { ReadFractalConfigFileFunction readFractalConfigFileFunction; readFractalConfigFileFunction = GetReadFractalConfigFileFunction(formatStr); res = (readFractalConfigFileFunction == NULL); } end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } return !res; } int ReadFractalConfigFileBody(FractalConfig *fractalConfig, const char *fileName, FILE *file, const char *format) { FractalNow_message(stdout, T_VERBOSE, "Reading fractal config file body...\n"); int res = 0; ReadFractalConfigFileFunction readFractalConfigFile; readFractalConfigFile = GetReadFractalConfigFileFunction(format); if (readFractalConfigFile == NULL) { FractalNow_werror("Unsupported fractal config format '%s'.\n", format); } res |= readFractalConfigFile(fractalConfig, fileName, file); end: FractalNow_message(stdout, T_VERBOSE, "Reading fractal config file body : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } int ReadFractalConfigFile(FractalConfig *fractalConfig, const char *fileName) { FractalNow_message(stdout, T_NORMAL, "Reading fractal configuration file...\n"); int res = 0; FILE *file; file=fopen(fileName,"r"); if (!file) { FractalNow_open_werror(fileName); } char formatStr[256]; if (readString(file, formatStr) < 1) { FractalNow_read_werror(fileName); } res = ReadFractalConfigFileBody(fractalConfig, fileName, file, formatStr); end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } FractalNow_message(stdout, T_NORMAL, "Reading fractal configuration file : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } int WriteFractalConfigFileV075(const FractalConfig *fractalConfig, const char *fileName, FILE *file) { int res = 0; const char fractalFormat[] = "f075"; const char renderingFormat[] = "r075"; res |= WriteFractalFileBody(&fractalConfig->fractal, fileName, file, fractalFormat); if (res) { FractalNow_werror("Failed to write fractal file.\n"); } res |= WriteRenderingFileBody(&fractalConfig->render, fileName, file, renderingFormat); if (res) { FractalNow_werror("Failed to read rendering file.\n"); } end: return res; } WriteFractalConfigFileFunction GetWriteFractalConfigFileFunction(const char *format) { if (strlen(format) != 4) { return NULL; } WriteFractalConfigFileFunction writeFractalConfigFile = NULL; char formatStr[5]; strcpy(formatStr, format); toLowerCase(formatStr); uint_fast32_t i; for (i = 0; i < nbFractalConfigFormats; ++i) { if (strcmp(formatStr, fractalConfigFormatStr[i]) == 0) { writeFractalConfigFile = writeFractalConfigFileFunction[i]; break; } } return writeFractalConfigFile; } int WriteFractalConfigFileBody(const FractalConfig *fractalConfig, const char *fileName, FILE *file, const char *format) { FractalNow_message(stdout, T_VERBOSE, "Writing fractal config file body...\n"); int res = 0; WriteFractalConfigFileFunction writeFractalConfigFile; writeFractalConfigFile = GetWriteFractalConfigFileFunction(format); if (writeFractalConfigFile == NULL) { FractalNow_werror("Unsupported fractal config format '%s'.\n", format); } res |= writeFractalConfigFile(fractalConfig, fileName, file); end: FractalNow_message(stdout, T_VERBOSE, "Writing fractal config file body : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } int WriteFractalConfigFile(const FractalConfig *fractalConfig, const char *fileName) { FractalNow_message(stdout, T_NORMAL, "Writing fractal configuration file...\n"); int res = 0; FILE *file; file=fopen(fileName,"w"); if (!file) { FractalNow_open_werror(fileName); } const char *format = fractalConfigFormatStr[nbFractalConfigFormats-1]; if (writeString(file, format, "\n") < 0) { FractalNow_write_werror(fileName); } res = WriteFractalConfigFileBody(fractalConfig, fileName, file, format); end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } FractalNow_message(stdout, T_NORMAL, "Writing fractal configuration file : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } void FreeFractalConfig(FractalConfig fractalConfig) { FreeFractal(fractalConfig.fractal); FreeRenderingParameters(fractalConfig.render); } fractalnow-0.8.2/examples/config_files/config10.config000664 001750 001750 00000000273 13175112471 022653 0ustar00mpegmpeg000000 000000 c075 julia 0.285 0.01 0 0 2.47464114832536 2.47464114832536 10000000 1000 1 0x0 averagecoloring stripe 1 linear cuberoot 1.35 0 0 0x39a0 0.25 0xffffff 0.5 0xfffe43 0.75 0xbf0800 1 0x39a0 fractalnow-0.8.2/man/000775 001750 001750 00000000000 13175115345 014365 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/lib/src/complex_wrapper.c000664 001750 001750 00000001724 13175112471 020523 0ustar00mpegmpeg000000 000000 /* * complex_wrapper.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "complex_wrapper.h" #ifdef _USE_BUILTIN_COMPLEX #include "builtin_complex.c" #else #include "c99_complex_wrapper.c" #endif fractalnow-0.8.2/lib/src/000775 001750 001750 00000000000 13175115345 015147 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/lib/src/color.c000664 001750 001750 00000007371 13175115345 016441 0ustar00mpegmpeg000000 000000 /* * color.c -- part of FractalNow * * Copyright (c) 2011-2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "color.h" #include "error.h" #include #include Color ColorFromRGB(uint8_t bytesPerComponent, uint16_t r, uint16_t g, uint16_t b) { if (bytesPerComponent != 1 && bytesPerComponent != 2) { FractalNow_error("Invalid bytes per component.\n"); } Color res; res.bytesPerComponent = bytesPerComponent; res.r = r; res.g = g; res.b = b; return res; } inline Color ColorFromUint32(uint32_t color) { Color res; res.r = GET_R8(color); res.g = GET_G8(color); res.b = GET_B8(color); res.bytesPerComponent = 1; return res; } inline Color ColorFromUint64(uint64_t color) { Color res; res.r = GET_R16(color); res.g = GET_G16(color); res.b = GET_B16(color); res.bytesPerComponent = 2; return res; } Color Color16(Color color) { Color res; if (color.bytesPerComponent == 2) { res = color; } else { res.bytesPerComponent = 2; res.r = round(color.r * UINT16_MAX / UINT8_MAX); res.g = round(color.g * UINT16_MAX / UINT8_MAX); res.b = round(color.b * UINT16_MAX / UINT8_MAX); } return res; } Color Color8(Color color) { Color res; if (color.bytesPerComponent == 1) { res = color; } else { res.bytesPerComponent = 1; res.r = round(color.r * UINT8_MAX / UINT16_MAX); res.g = round(color.g * UINT8_MAX / UINT16_MAX); res.b = round(color.b * UINT8_MAX / UINT16_MAX); } return res; } int CompareColors(const Color color1, const Color color2) { return (color1.bytesPerComponent != color2.bytesPerComponent || color1.r != color2.r || color1.g != color2.g || color1.b != color2.b); } Color MixColors(Color C1, double weight1, Color C2, double weight2) { Color res; res.bytesPerComponent = C1.bytesPerComponent; res.r = C1.r * weight1 + C2.r * weight2; res.g = C1.g * weight1 + C2.g * weight2; res.b = C1.b * weight1 + C2.b * weight2; return res; } inline double ColorManhattanDistance(Color C1, Color C2) { double res = 0; uint_fast32_t sum = (labs(C1.r-(long int)C2.r)+labs(C1.g-(long int)C2.g)+ labs(C1.b-(long int)C2.b)); switch (C1.bytesPerComponent) { case 1: res = sum / (double)(3*UINT8_MAX); break; case 2: res = sum / (double)(3*UINT16_MAX); break; default: FractalNow_error("Invalid bytes per component.\n"); break; } return res; } inline double QuadAvgDissimilarity(const Color C[4]) { Color avg; avg.r = (C[0].r + C[1].r + C[2].r + C[3].r) / 4; avg.g = (C[0].g + C[1].g + C[2].g + C[3].g) / 4; avg.b = (C[0].b + C[1].b + C[2].b + C[3].b) / 4; return (ColorManhattanDistance(C[0],avg)+ ColorManhattanDistance(C[1],avg)+ ColorManhattanDistance(C[2],avg)+ ColorManhattanDistance(C[3],avg)) / 4; } inline Color QuadLinearInterpolation(const Color C[4], double x, double y) { Color res; res.bytesPerComponent = C[0].bytesPerComponent; res.r = (C[0].r*(1.-x)+C[1].r*x)*(1.-y) + (C[2].r*(1.-x)+C[3].r*x)*y; res.g = (C[0].g*(1.-x)+C[1].g*x)*(1.-y) + (C[2].g*(1.-x)+C[3].g*x)*y; res.b = (C[0].b*(1.-x)+C[1].b*x)*(1.-y) + (C[2].b*(1.-x)+C[3].b*x)*y; return res; } fractalnow-0.8.2/gui/include/gradient_editor.h000664 001750 001750 00000002646 13175112471 021342 0ustar00mpegmpeg000000 000000 /**************************************************************************** ** ** This file is based on some files of the demonstration applications of the ** Qt Toolkit. ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Modified to be used as a part of FractalNow: ** Copyright (c) 2012 Marc Pegon ** ** This file can be distributed and/or modified under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation. ** You should have received a copy of the GNU General Public License ** along with this file; if not, write to the Free Software Foundation, Inc., ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ** ****************************************************************************/ #ifndef __GRADIENT_EDITOR_H__ #define __GRADIENT_EDITOR_H__ #include "gradient_label.h" #include "shade_widget.h" class GradientEditor : public QWidget { Q_OBJECT public: GradientEditor(QWidget *parent = 0); void setGradientStops(const QGradientStops &stops); QSize sizeHint() const { return QSize(480,320); } public slots: void pointsUpdated(); signals: void gradientStopsChanged(const QGradientStops &stops); private: GradientLabel *m_gradient_label; ShadeWidget *m_red_shade; ShadeWidget *m_green_shade; ShadeWidget *m_blue_shade; }; #endif fractalnow-0.8.2/lib/include/fractal_config.h000664 001750 001750 00000014203 13175112471 021112 0ustar00mpegmpeg000000 000000 /* * fractal_config.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal_config.h * \brief Header file related to fractal configuration structure. * * A fractal configuration is the conjunction of a fractal and * rendering parameters. * A configuration file is more or less the concatenation of a fractal * file and a rendering file. */ #ifndef __FRACTAL_CONFIG_H__ #define __FRACTAL_CONFIG_H__ #include "fractal.h" #include "fractal_rendering_parameters.h" #include #ifdef __cplusplus extern "C" { #endif /** * \struct FractalConfig * \brief Structure containing fractal and fractal rendering parameters. */ /** * \typedef FractalConfig * \brief Convenient typedef for struct FractalConfig. */ typedef struct FractalConfig { Fractal fractal; /*!< Fractal.*/ RenderingParameters render; /*!< Rendering parameters.*/ } FractalConfig; /** * \fn void InitFractalConfig(FractalConfig *config, Fractal fractal, RenderingParameters render) * \brief Initialize fractal config. * * Fractal and rendering parameters will be owned by fractal config, * and will be free'd when fractal config is free'd. * * \param config Pointer to structure to initialize. * \param fractal Fractal * \param render Rendering parameters. */ void InitFractalConfig(FractalConfig *config, Fractal fractal, RenderingParameters render); /** * \fn FractalConfig CopyFractalConfig(const FractalConfig *config) * \brief Copy fractal configuration. * * \param config Pointer to fractal configuration to copy. * \return Copy of fractal configuration. */ FractalConfig CopyFractalConfig(const FractalConfig *config); /** * \fn void ResetFractal(FractalConfig *config, Fractal fractal) * \brief Reset fractal. * * Fractal will be owned by fractal config, and * will be free'd when fractal config is free'd. * * \param config Fractal config to be changed. * \param fractal New fractal. */ void ResetFractal(FractalConfig *config, Fractal fractal); /** * \fn void ResetRenderingParameters(FractalConfig *config, RenderingParameters render) * \brief Reset rendering parameters. * * RenderingParameters will be owned by fractal config, and * will be free'd when fractal config is free'd. * * \param config Fractal config to be changed. * \param render New rendering parameters. */ void ResetRenderingParameters(FractalConfig *config, RenderingParameters render); /** * \fn int isSupportedFractalConfigFile(const char *fileName) * \brief Check whether a file is a supported fractal configuration file. * * \param fileName File name. * \return 1 if file is a supported fractal config file, 0 otherwise. */ int isSupportedFractalConfigFile(const char *fileName); /** * \fn int ReadFractalConfigFileBody(FractalConfig *fractalConfig, const char *fileName, FILE *file, const char *format) * \brief Read fractal configuration from fractal configuration file body. * * The body of a configuration file is everything that comes * after the format version.\n * fileName is used only for error messages.\n * This function should only be used internally by the library. * * \param fractalConfig Pointer to the configuration file structure to create. * \param fileName Fractal configuration file name. * \param file Pointer to opened file, positioned at the beginning of the body. * \param format Fractal configuration file format. * \return 0 in case of success, 1 in case of failure. */ int ReadFractalConfigFileBody(FractalConfig *fractalConfig, const char *fileName, FILE *file, const char *format); /** * \fn int ReadFractalConfigFile(FractalConfig *fractalConfig, const char *fileName) * \brief Read and parse fractal configuration file. * * \param fractalConfig Pointer to the structure to store fractal configuration. * \param fileName Name of file containing fractal configuration. * \return 0 in case of success, 1 in case of failure. */ int ReadFractalConfigFile(FractalConfig *fractalConfig, const char *fileName); /** * \fn int WriteFractalConfigFileBody(const FractalConfig *fractalConfig, const char *fileName, FILE *file, const char *format) * \brief Write fractal configuration file body. * * The body of a configuration file is everything that comes * after the format version.\n * fileName is used only for error messages.\n * This function should only be used internally by the library. * * \param fractalConfig Fractal configuration to write. * \param fileName Fractal configuration file name. * \param file Pointer to opened file, positioned at the beginning of the body. * \param format Fractal configuration file format. * \return 0 in case of success, 1 in case of failure. */ int WriteFractalConfigFileBody(const FractalConfig *fractalConfig, const char *fileName, FILE *file, const char *format); /** * \fn int WriteFractalConfigFile(const FractalConfig *fractalConfig, const char *fileName) * \brief Write fractal configuration file. * * \param fractalConfig Fractal configuration file to write. * \param fileName Name of file containing fractal configuration. * \return 0 in case of success, 1 in case of failure. */ int WriteFractalConfigFile(const FractalConfig *fractalConfig, const char *fileName); /** * \fn void FreeFractalConfig(FractalConfig fractalConfig) * \brief Free a FractalConfig structure. * * \param fractalConfig FractalConfig structure to be freed. */ void FreeFractalConfig(FractalConfig fractalConfig); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/lib/src/image.c000664 001750 001750 00000032513 13175112471 016376 0ustar00mpegmpeg000000 000000 /* * image.c -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "image.h" #include "filter.h" #include "misc.h" #include "uirectangle.h" #include #include #include #define HandleRequests(max_counter) \ if (counter == max_counter) {\ HandlePauseRequest(threadArgHeader);\ cancelRequested =\ CancelTaskRequested(threadArgHeader);\ counter = 0;\ } else {\ ++counter;\ } inline void CreateImage(Image *image, uint_fast32_t width, uint_fast32_t height, uint_fast8_t bytesPerComponent) { if (bytesPerComponent != 1 && bytesPerComponent != 2) { FractalNow_error("Invalid bytes per component. Only 1 and 2 are allowed.\n"); } image->data = (uint8_t *)safeCalloc("image data", width*height, 4*bytesPerComponent); image->data_is_external = 0; image->width = width; image->height = height; image->bytesPerComponent = bytesPerComponent; } void CreateImage2(Image *image, uint8_t *data, uint_fast32_t width, uint_fast32_t height, uint_fast8_t bytesPerComponent) { if (bytesPerComponent != 1 && bytesPerComponent != 2) { FractalNow_error("Invalid bytes per component. Only 1 and 2 are allowed.\n"); } image->data = data; image->data_is_external = 1; image->width = width; image->height = height; image->bytesPerComponent = bytesPerComponent; } Image CloneImage(const Image *image) { Image res; CreateImage(&res, image->width, image->height, image->bytesPerComponent); memcpy(res.data, image->data, image->width*image->height*4*image->bytesPerComponent); return res; } static inline uint8_t *ImageRGB8ToBytesArray(const Image *image) { if (image->width == 0 || image->height == 0) { return NULL; } uint8_t *res = (uint8_t *)safeCalloc("image bytes array", image->width*image->height, 3*image->bytesPerComponent); uint32_t *p_data32 = (uint32_t *)image->data; uint32_t data32; uint8_t *p_res = res; for (uint_fast32_t i = 0; i < image->height; ++i) { for (uint_fast32_t j = 0; j < image->width; ++j) { data32 = *p_data32; *(p_res++) = GET_R8(data32); *(p_res++) = GET_G8(data32); *(p_res++) = GET_B8(data32); ++p_data32; } } return res; } static inline uint8_t *ImageRGB16ToBytesArray(const Image *image) { if (image->width == 0 || image->height == 0) { return NULL; } uint8_t *res = (uint8_t *)safeCalloc("image bytes array", image->width*image->height, 3*image->bytesPerComponent); uint64_t *p_data64 = (uint64_t *)image->data; uint64_t data64; uint16_t r, g, b; uint8_t *p_res = res; for (uint_fast32_t i = 0; i < image->height; ++i) { for (uint_fast32_t j = 0; j < image->width; ++j) { data64 = *p_data64; /* We want the components in the order RGB, so we need to extract * them from uint64_t (the machine can be MSB first, or LSB first..) */ r = GET_R16(data64); g = GET_G16(data64); b = GET_B16(data64); /* Then we want for each component the most significant byte first.*/ *(p_res++) = r >> 8; *(p_res++) = r & 0xFF; *(p_res++) = g >> 8; *(p_res++) = g & 0xFF; *(p_res++) = b >> 8; *(p_res++) = b & 0xFF; ++p_data64; } } return res; } uint8_t *ImageToBytesArray(const Image *image) { uint8_t *res; switch(image->bytesPerComponent) { case 1: res = ImageRGB8ToBytesArray(image); break; case 2: res = ImageRGB16ToBytesArray(image); break; default: FractalNow_error("Invalid bytes per component (%"PRIuFAST8").\n", image->bytesPerComponent); break; } return res; } typedef enum { LEFT = 0, TOP, RIGHT, BOTTOM, TOPLEFT, TOPRIGHT, BOTTOMRIGHT, BOTTOMLEFT, CENTER } Region; inline Color iGetPixelUnsafe(const Image *image, uint_fast32_t x, uint_fast32_t y) { Color res; res.bytesPerComponent = image->bytesPerComponent; switch (res.bytesPerComponent) { case 1: { uint32_t data32 = *((uint32_t *)(image->data) + y*image->width+x); res.r = GET_R8(data32); res.g = GET_G8(data32); res.b = GET_B8(data32); break; } case 2: { uint64_t data64 = *((uint64_t *)(image->data) + y*image->width+x); res.r = GET_R16(data64); res.g = GET_G16(data64); res.b = GET_B16(data64); } break; default: FractalNow_error("Invalid bytes per component.\n"); break; } return res; } Region iGetImageRegion(const Image *image, int_fast64_t x, int_fast64_t y) { Region region; if (x < 0) { if (y < 0) { region = TOPLEFT; } else if ((uint_fast32_t)y >= image->height) { region = BOTTOMLEFT; } else { region = LEFT; } } else if ((uint_fast32_t)x >= image->width) { if (y < 0) { region = TOPRIGHT; } else if ((uint_fast32_t)y >= image->height) { region = BOTTOMRIGHT; } else { region = RIGHT; } } else { if (y < 0) { region = TOP; } else if ((uint_fast32_t)y >= image->height) { region = BOTTOM; } else { region = CENTER; } } return region; } Color blackColorRGB8 = {1, 0, 0, 0}; Color blackColorRGB16 = {2, 0, 0, 0}; Color iGetPixel(const Image *image, int_fast64_t x, int_fast64_t y) { if (image->width == 0 || image->height == 0) { if (image->bytesPerComponent == 1) { return blackColorRGB8; } else { return blackColorRGB16; } } Region region = iGetImageRegion(image, x, y); Color res; switch (region) { case TOPLEFT: res = iGetPixelUnsafe(image, 0, 0); break; case TOPRIGHT: res = iGetPixelUnsafe(image, image->width-1, 0); break; case BOTTOMLEFT: res = iGetPixelUnsafe(image, 0, image->height-1); break; case BOTTOMRIGHT: res = iGetPixelUnsafe(image, image->width-1, image->height-1); break; case TOP: res = iGetPixelUnsafe(image, x, 0); break; case LEFT: res = iGetPixelUnsafe(image, 0, y); break; case RIGHT: res = iGetPixelUnsafe(image, image->width-1, y); break; case BOTTOM: res = iGetPixelUnsafe(image, x, image->height-1); break; case CENTER: res = iGetPixelUnsafe(image, x, y); break; default: FractalNow_error("Unknown region.\n"); break; } return res; } inline void PutPixelUnsafe(Image *image, uint_fast32_t x, uint_fast32_t y, Color color) { switch (image->bytesPerComponent) { case 1: { uint32_t *data32 = (uint32_t *)(image->data) + y*image->width+x; *data32 = RGB8_TO_UINT32(color.r, color.g, color.b); break; } case 2: { uint64_t *data64 = (uint64_t *)(image->data) + y*image->width+x; *data64 = RGB16_TO_UINT64(color.r, color.g, color.b); } break; default: FractalNow_error("Invalid bytes per component.\n"); break; } } char applyGaussianBlurMessage[] = "Applying gaussian blur"; Task *CreateApplyGaussianBlurTask(Image *dst, Image *temp, const Image *src, double radius, uint_fast32_t nbThreads) { Filter horizontalGaussianFilter; Filter verticalGaussianFilter; CreateHorizontalGaussianFilter2(&horizontalGaussianFilter, radius); CreateVerticalGaussianFilter2(&verticalGaussianFilter, radius); Task *subTasks[2]; subTasks[0] = CreateApplyFilterTask(temp, src, &horizontalGaussianFilter, nbThreads); subTasks[1] = CreateApplyFilterTask(dst, temp, &verticalGaussianFilter, nbThreads); Task *res = CreateCompositeTask(applyGaussianBlurMessage, 2, subTasks); FreeFilter(horizontalGaussianFilter); FreeFilter(verticalGaussianFilter); return res; } void ApplyGaussianBlur(Image *dst, const Image *src, double radius, Threads *threads) { Image temp; CreateImage(&temp, src->width, src->height, src->bytesPerComponent); Task *task = CreateApplyGaussianBlurTask(dst, &temp, src, radius, threads->N); int unused = ExecuteTaskBlocking(task, threads); UNUSED(unused); FreeImage(temp); } typedef struct s_DownscaleImageArguments { uint_fast32_t threadId; Image *dst; uint_fast32_t nbRectangles; UIRectangle *rectangles; const Image *src; double invScaleX; double invScaleY; Filter *horizontalGaussianFilter; Filter *verticalGaussianFilter; } DownscaleImageArguments; void FreeDownscaleImageArguments(void *arg) { DownscaleImageArguments *c_arg = (DownscaleImageArguments *)arg; if (c_arg->threadId == 0) { free(c_arg->rectangles); FreeFilter(*c_arg->horizontalGaussianFilter); FreeFilter(*c_arg->verticalGaussianFilter); free(c_arg->horizontalGaussianFilter); free(c_arg->verticalGaussianFilter); } } void *DownscaleImageThreadRoutine(void *arg) { ThreadArgHeader *threadArgHeader = GetThreadArgHeader(arg); DownscaleImageArguments *c_arg = (DownscaleImageArguments *)GetThreadArgBody(arg); Image *dst = c_arg->dst; const Image *src = c_arg->src; double invScaleX = c_arg->invScaleX; double invScaleY = c_arg->invScaleY; Filter *horizontalGaussianFilter = c_arg->horizontalGaussianFilter; Filter *verticalGaussianFilter = c_arg->verticalGaussianFilter; Image tmpImage; CreateImage(&tmpImage, horizontalGaussianFilter->sx, 1, src->bytesPerComponent); uint_fast32_t nbRectangles = c_arg->nbRectangles; UIRectangle *dstRect; uint_fast32_t rectHeight; uint_fast32_t counter = 0; int cancelRequested = CancelTaskRequested(threadArgHeader); for (uint_fast32_t i = 0; i < nbRectangles && !cancelRequested; ++i) { dstRect = &c_arg->rectangles[i]; rectHeight = dstRect->y2+1 - dstRect->y1; for (uint_fast32_t j = dstRect->y1; j <= dstRect->y2 && !cancelRequested; ++j) { SetThreadProgress(threadArgHeader, 100 * (i * rectHeight + (j-dstRect->y1)) / (rectHeight * nbRectangles)); uint_fast32_t y = (j+0.5)*invScaleY; for (uint_fast32_t k = dstRect->x1; k <= dstRect->x2 && !cancelRequested; ++k) { HandleRequests(32); uint_fast32_t x = (k+0.5)*invScaleX; for (uint_fast32_t l = 0; l < horizontalGaussianFilter->sx; ++l) { PutPixelUnsafe(&tmpImage, l, 0, ApplyFilterOnSinglePixel(src, x-horizontalGaussianFilter->cx+l, y, verticalGaussianFilter)); } PutPixelUnsafe(dst, k, j, ApplyFilterOnSinglePixel(&tmpImage, horizontalGaussianFilter->cx, 0, horizontalGaussianFilter)); } } } SetThreadProgress(threadArgHeader, 100); FreeImage(tmpImage); int canceled = CancelTaskRequested(threadArgHeader); return (canceled ? PTHREAD_CANCELED : NULL); } char downscaleImageMessage[] = "Downscaling image"; Task *CreateDownscaleImageTask(Image *dst, const Image *src, uint_fast32_t nbThreads) { if (src->width == 0 || src->height == 0 || dst->width == 0 || dst->height == 0) { return DoNothingTask(); } if (dst->width > src->width || dst->height > src->height) { FractalNow_error("Downscaling to a bigger image makes no sense.\n"); } double invScaleX = src->width / (double)dst->width; double invScaleY = src->height / (double)dst->height; Filter *horizontalGaussianFilter = (Filter *)safeMalloc("horizontal gaussian filter", sizeof(Filter)); Filter *verticalGaussianFilter = (Filter *)safeMalloc("vertical gaussian filter", sizeof(Filter)); CreateHorizontalGaussianFilter2(horizontalGaussianFilter, invScaleX); CreateVerticalGaussianFilter2(verticalGaussianFilter, invScaleY); uint_fast32_t nbPixels = dst->width*dst->height; uint_fast32_t nbThreadsNeeded = nbThreads; uint_fast32_t rectanglesPerThread = DEFAULT_RECTANGLES_PER_THREAD; if (nbPixels <= nbThreadsNeeded) { nbThreadsNeeded = nbPixels; rectanglesPerThread = 1; } else if (nbPixels < nbThreadsNeeded*rectanglesPerThread) { rectanglesPerThread = nbPixels / nbThreadsNeeded; } uint_fast32_t nbRectangles = nbThreadsNeeded*rectanglesPerThread; UIRectangle *rectangle; rectangle = (UIRectangle *)safeMalloc("rectangles", nbRectangles * sizeof(UIRectangle)); InitUIRectangle(&rectangle[0], 0, 0, dst->width-1, dst->height-1); if (CutUIRectangleInN(rectangle[0], nbRectangles, rectangle)) { FractalNow_error("Could not cut rectangle ((%"PRIuFAST32",%"PRIuFAST32"),\ (%"PRIuFAST32",%"PRIuFAST32") in %"PRIuFAST32" parts.\n", rectangle[0].x1, rectangle[0].y1, rectangle[0].x2, rectangle[0].y2, nbRectangles); } DownscaleImageArguments *arg; arg = (DownscaleImageArguments *)safeMalloc("arguments", nbThreadsNeeded * sizeof(DownscaleImageArguments)); for (uint_fast32_t i = 0; i < nbThreadsNeeded; ++i) { arg[i].threadId = i; arg[i].dst = dst; arg[i].nbRectangles = rectanglesPerThread; arg[i].rectangles = &rectangle[i*rectanglesPerThread]; arg[i].src = src; arg[i].invScaleX = invScaleX; arg[i].invScaleY = invScaleY; /* Filters copied to avoid concurrent read. */ arg[i].horizontalGaussianFilter = horizontalGaussianFilter; arg[i].verticalGaussianFilter = verticalGaussianFilter; } Task *res = CreateTask(downscaleImageMessage, nbThreadsNeeded, arg, sizeof(DownscaleImageArguments), DownscaleImageThreadRoutine, FreeDownscaleImageArguments); free(arg); return res; } void DownscaleImage(Image *dst, const Image *src, Threads *threads) { Task *task = CreateDownscaleImageTask(dst, src, threads->N); int unused = ExecuteTaskBlocking(task, threads); UNUSED(unused); } void FreeImage(Image image) { if (image.width != 0 && image.height != 0 && !image.data_is_external) { free(image.data); } } fractalnow-0.8.2/lib/include/fractal_compute_engine.h000664 001750 001750 00000007754 13175115345 022666 0ustar00mpegmpeg000000 000000 /* * fractal_compute_engine.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal_compute_engine.h * \brief Header file related to fractal computation engines. * \author Marc Pegon */ #ifndef __FRACTAL_COMPUTE_ENGINE_H__ #define __FRACTAL_COMPUTE_ENGINE_H__ #include "float_precision.h" #include "fractal_addend_function.h" #include "fractal_cache.h" #include "fractal_coloring.h" #include "fractal_formula.h" #include "fractal_iteration_count.h" #include "fractal_rendering_parameters.h" #ifdef __cplusplus extern "C" { #endif struct Fractal; /** * \struct FractalEngine * \brief Engine to compute fractal engine (specific compiled loop and data). * * A FractalEngine structure contains a pointer to a function that computes * fractal for given parameters efficiently, as well as all the data it needs.\n * * The cache entry returned by fractal loop can be added to a cache, in which * case it will be free'd automatically (when new entries come, or when cache * is free'd), or just free'd if cache is disabled. */ /** * \typedef FractalEngine * \brief Convenient typedef for struct FractalEngine. */ typedef struct FractalEngine { CacheEntry (*fractalLoop)(void *data, const struct Fractal *fractal, const RenderingParameters *render, uint_fast32_t x, uint_fast32_t y, uint_fast32_t width, uint_fast32_t height); /*!< Fractal loop function.*/ void (*freeEngineData)(void *data); /*!< Function to free engine data.*/ void *data; /*!< Engine data (used by fractal loop).*/ } FractalEngine; /** * \fn int CreateFractalEngine(FractalEngine *engine, const struct Fractal *fractal, const RenderingParameters *render, FloatPrecision floatPrecision) * \brief Create fractal engine for given fractal, rendering parameters and float precision. * * \param engine Pointer to structure to be initialized. * \param fractal Fractal to be computed. * \param render Rendenring parameters. * \param floatPrecision Float precision. * \return 0 in case of success, 1 otherwise. */ int CreateFractalEngine(FractalEngine *engine, const struct Fractal *fractal, const RenderingParameters *render, FloatPrecision floatPrecision); /** * \fn void FreeFractalEngine(FractalEngine *engine) * \brief Free fractal engine. * * \param engine Pointer to fractal structure to be free'd. */ void FreeFractalEngine(FractalEngine *engine); /** * \fn CacheEntry RunFractalEngine(const FractalEngine *engine, const struct Fractal *fractal, const RenderingParameters *render, uint_fast32_t x, uint_fast32_t y, uint_fast32_t width, uint_fast32_t height) * \brief Run fractal engine at given point. * * Compute pixel (x,y) of an image of size (width, height). * \see CacheEntry * * \param engine Fractal engine to be run. * \param fractal Fractal to be computed. * \param render Rendering parameters. * \param x Pixel X coordinate. * \param y Pixel Y coordinate. * \param width Image width. * \param height Image height. * \return Cache entry that can be added to cache or just used and free'd. */ CacheEntry RunFractalEngine(const FractalEngine *engine, const struct Fractal *fractal, const RenderingParameters *render, uint_fast32_t x, uint_fast32_t y, uint_fast32_t width, uint_fast32_t height); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/config_files/config13.config000664 001750 001750 00000000230 13175112471 022647 0ustar00mpegmpeg000000 000000 c075 julia 0.5 0.25 0 0 2.57775119617225 2.57775119617225 1E+30 100 1 0x0 averagecoloring curvature linear cube 0.075 0.5 0 0xffffff 0.5 0x0 1 0xffffff fractalnow-0.8.2/gui/src/fractal_explorer.cpp000664 001750 001750 00000111315 13175125115 021223 0ustar00mpegmpeg000000 000000 /* * fractal_explorer.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "fractal_explorer.h" #include #include #include #include #include #include #include #include #include FractalExplorer::FractalExplorer(const FractalConfig &fractalConfig, uint_fast32_t width, uint_fast32_t height, uint_fast32_t minAntiAliasingSize, uint_fast32_t maxAntiAliasingSize, uint_fast32_t antiAliasingSizeIteration, uint_fast32_t quadInterpolationSize, double colorDissimilarityThreshold, double adaptiveAAMThreshold, uint_fast32_t nbThreads, QWidget *parent, Qt::WindowFlags f) : QLabel(parent, f), fractal(this->fractalConfig.fractal), render(this->fractalConfig.render), quadInterpolationSize(quadInterpolationSize), colorDissimilarityThreshold(colorDissimilarityThreshold), adaptiveAAMThreshold(adaptiveAAMThreshold) { setCursor(QCursor(Qt::OpenHandCursor)); setContextMenuPolicy(Qt::DefaultContextMenu); mpfr_init(fractalCenterXOnPress); mpfr_init(fractalCenterYOnPress); this->fractalConfig = CopyFractalConfig(&fractalConfig); if (fractalConfig.render.bytesPerComponent == 2) { QMessageBox::critical(this, tr("Gradient color depth is 16 bits."), tr("16-bits gradient will be converted to 8-bits gradient.")); Gradient newGradient = Gradient8(&this->render.gradient); ResetGradient(&this->render, newGradient); FreeGradient(newGradient); } this->initialFractalConfig = CopyFractalConfig(&this->fractalConfig); this->initialWidth = width; this->initialHeight = height; this->minAntiAliasingSize = minAntiAliasingSize; this->maxAntiAliasingSize = maxAntiAliasingSize; this->antiAliasingSizeIteration = antiAliasingSizeIteration; drawingPaused = false; redrawFractal = false; movingFractalDeferred = false; movingFractalRealTime = false; fractalMoved = false; /* Create QImage and Image (from fractal lib) */ fractalQImage = new QImage(width, height, QImage::Format_RGB32); fractalQImage->fill(0); CreateImage2(&fractalImage, fractalQImage->bits(), width, height, 1); adjustSpan(); restoreInitialStateAction = new QAction(tr("Restore &initial state"), this); restoreInitialStateAction->setIconText(tr("Initial state")); restoreInitialStateAction->setShortcut(QKeySequence::MoveToStartOfDocument); restoreInitialStateAction->setIcon(QApplication::style()->standardIcon( QStyle::SP_DirHomeIcon)); connect(restoreInitialStateAction, SIGNAL(triggered()), this, SLOT(restoreInitialState())); stopDrawingAction = new QAction(tr("&Stop drawing"), this); stopDrawingAction->setIconText(tr("Stop")); stopDrawingAction->setShortcut(Qt::Key_S); stopDrawingAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_BrowserStop)); connect(stopDrawingAction, SIGNAL(triggered()), this, SLOT(stopDrawing())); refreshAction = new QAction(tr("&Refresh"), this); refreshAction->setShortcut(QKeySequence::Refresh); refreshAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_BrowserReload)); connect(refreshAction, SIGNAL(triggered()), this, SLOT(refresh())); zoomInAction = new QAction(tr("Zoom in"), this); QList zoomInShortcuts; zoomInShortcuts << Qt::Key_Plus << QKeySequence::ZoomIn; zoomInAction->setShortcuts(zoomInShortcuts); connect(zoomInAction, SIGNAL(triggered()), this, SLOT(zoomInFractal())); zoomOutAction = new QAction(tr("Zoom out"), this); QList zoomOutShortcuts; zoomOutShortcuts << Qt::Key_Minus << QKeySequence::ZoomOut; zoomOutAction->setShortcuts(zoomOutShortcuts); connect(zoomOutAction, SIGNAL(triggered()), this, SLOT(zoomOutFractal())); moveLeftAction = new QAction(tr("Move left"), this); moveLeftAction->setShortcut(Qt::Key_Left); connect(moveLeftAction, SIGNAL(triggered()), this, SLOT(moveLeftFractal())); moveRightAction = new QAction(tr("Move right"), this); moveRightAction->setShortcut(Qt::Key_Right); connect(moveRightAction, SIGNAL(triggered()), this, SLOT(moveRightFractal())); moveUpAction = new QAction(tr("Move up"), this); moveUpAction->setShortcut(Qt::Key_Up); connect(moveUpAction, SIGNAL(triggered()), this, SLOT(moveUpFractal())); moveDownAction = new QAction(tr("Move down"), this); moveDownAction->setShortcut(Qt::Key_Down); connect(moveDownAction, SIGNAL(triggered()), this, SLOT(moveDownFractal())); int failure = CreateFractalCache(&cache, 0); if (failure) { emit fractalCacheSizeChanged(cache.size); QMessageBox::critical(this, tr("Failed to resize cache"), tr("Could not allocate memory for cache.")); } pCache = NULL; solidGuessing = true; floatPrecision = FP_DOUBLE; threads = CreateThreads(nbThreads); task = DoNothingTask(); LaunchTask(task, threads); /* Create timer to repaint fractalImageLabel regularly. */ timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout())); timer->start(10); } FractalExplorer::~FractalExplorer() { cancelActionIfNotFinished(); FreeTask(task); DestroyThreads(threads); FreeFractalConfig(fractalConfig); FreeFractalConfig(initialFractalConfig); FreeImage(fractalImage); FreeFractalCache(&cache); mpfr_clear(fractalCenterXOnPress); mpfr_clear(fractalCenterYOnPress); delete fractalQImage; } bool FractalExplorer::getFractalCacheEnabled() const { return (pCache != NULL); } void FractalExplorer::useFractalCache(bool enabled) { bool changed = (enabled == (pCache == NULL)); if (changed) { cancelActionIfNotFinished(); if (enabled) { pCache = &cache; } else { pCache = NULL; } refresh(); } } int FractalExplorer::getFractalCacheSize() const { return (int)cache.size; } void FractalExplorer::resizeFractalCache(int size) { if (size < 0) { size = 0; } int failure = ResizeCacheThreadSafe(&cache, size); if (failure) { emit fractalCacheSizeChanged(cache.size); QMessageBox::critical(this, tr("Failed to resize cache"), tr("Could not allocate memory for cache.")); } } bool FractalExplorer::getSolidGuessingEnabled() const { return solidGuessing; } void FractalExplorer::setSolidGuessingEnabled(bool enabled) { bool changed = (enabled != solidGuessing); if (changed) { cancelActionIfNotFinished(); solidGuessing = enabled; refresh(); } } void FractalExplorer::setFractalConfig(const FractalConfig &fractalConfig) { cancelActionIfNotFinished(); FractalConfig oldFractalConfig = this->fractalConfig; this->fractalConfig = CopyFractalConfig(&fractalConfig); if (this->fractalConfig.render.bytesPerComponent == 2) { QMessageBox::critical(this, tr("Gradient color depth is 16 bits."), tr("16-bits gradient will be converted to 8-bits gradient.")); Gradient newGradient = Gradient8(&this->fractalConfig.render.gradient); ResetGradient(&this->fractalConfig.render, newGradient); FreeGradient(newGradient); } FreeFractalConfig(oldFractalConfig); adjustSpan(); emit fractalChanged(fractal); emit renderingParametersChanged(render); refresh(); } void FractalExplorer::setFractal(const Fractal &fractal) { cancelActionIfNotFinished(); ResetFractal(&fractalConfig, fractal); adjustSpan(); emit fractalChanged(this->fractal); refresh(); } void FractalExplorer::setRenderingParameters(const RenderingParameters &render) { cancelActionIfNotFinished(); RenderingParameters newRender = CopyRenderingParameters(&render); if (newRender.bytesPerComponent == 2) { QMessageBox::critical(this, tr("Gradient color depth is 16 bits."), tr("16-bits gradient will be converted to 8-bits gradient.")); Gradient newGradient = Gradient8(&newRender.gradient); ResetGradient(&newRender, newGradient); FreeGradient(newGradient); } ResetRenderingParameters(&fractalConfig, newRender); FreeRenderingParameters(newRender); adjustSpan(); emit renderingParametersChanged(this->render); refresh(); } void FractalExplorer::setGradient(const Gradient &gradient) { cancelActionIfNotFinished(); if (gradient.bytesPerComponent == 2) { QMessageBox::critical(this, tr("Gradient color depth is 16 bits."), tr("16-bits gradient will be converted to 8-bits gradient.")); Gradient newGradient = Gradient8(&gradient); ResetGradient(&fractalConfig.render, newGradient); FreeGradient(newGradient); } else { ResetGradient(&fractalConfig.render, gradient); } adjustSpan(); emit renderingParametersChanged(render); refresh(); } void FractalExplorer::adjustSpan() { uint_fast32_t width = fractalImage.width; uint_fast32_t height = fractalImage.height; if (width != 0 && height != 0) { if (height / (double)width < 1) { mpfr_set(fractal.spanX, fractal.spanY, MPFR_RNDN); mpfr_mul_ui(fractal.spanX, fractal.spanX, width, MPFR_RNDN); mpfr_div_ui(fractal.spanX, fractal.spanX, height, MPFR_RNDN); } else { mpfr_set(fractal.spanY, fractal.spanX, MPFR_RNDN); mpfr_mul_ui(fractal.spanY, fractal.spanY, height, MPFR_RNDN); mpfr_div_ui(fractal.spanY, fractal.spanY, width, MPFR_RNDN); } reInitFractal(); } } void FractalExplorer::restoreInitialState() { setFractalConfig(initialFractalConfig); } const FractalConfig &FractalExplorer::getFractalConfig() const { return fractalConfig; } const Fractal &FractalExplorer::getFractal() const { return fractal; } const RenderingParameters &FractalExplorer::getRender() const { return render; } void FractalExplorer::resizeImage(uint_fast32_t width, uint_fast32_t height) { if (height == 0) { if (mpfr_cmp_ui(fractal.spanX, 0) == 0) { height = width; } else { mpfr_t tmp; mpfr_div(tmp, fractal.spanY, fractal.spanX, MPFR_RNDN); mpfr_mul_ui(tmp, tmp, width, MPFR_RNDN); height = mpfr_get_ld(tmp, MPFR_RNDN); } } double dx = width - (double)fractalImage.width; double dy = height - (double)fractalImage.height; if (fractalImage.width != 0) { mpfr_mul_d(fractal.spanX, fractal.spanX, 1. + dx/fractalImage.width, MPFR_RNDN); } if (fractalImage.height != 0) { mpfr_mul_d(fractal.spanY, fractal.spanY, 1. + dy/fractalImage.height, MPFR_RNDN); } reInitFractal(); cancelActionIfNotFinished(); Image newImage, oldImage; QImage *newQImage, *oldQImage; newQImage = new QImage(width, height, QImage::Format_RGB32); newQImage->fill(0); QPainter painter(newQImage); painter.setRenderHint(QPainter::SmoothPixmapTransform); QRectF srcRect(std::max(0.,-dx/2), std::max(0.,-dy/2), fractalImage.width+std::min(0.,dx), fractalImage.height+std::min(0.,dy)); QRectF dstRect(std::max(0.,dx/2), std::max(0.,dy/2), fractalImage.width-std::max(0.,-dx), fractalImage.height-std::max(0.,-dy)); painter.drawImage(dstRect, *fractalQImage, srcRect); CreateImage2(&newImage, newQImage->bits(), width, height, 1); oldImage = fractalImage; oldQImage = fractalQImage; fractalImage = newImage; fractalQImage = newQImage; FreeImage(oldImage); delete oldQImage; updateGeometry(); emit fractalChanged(fractal); refresh(); } void FractalExplorer::resizeEvent(QResizeEvent * event) { QSize size(event->size()); resizeImage(size.width(), size.height()); } void FractalExplorer::paintEvent(QPaintEvent *event) { UNUSED(event); setFocusPolicy(Qt::StrongFocus); if (fractalQImage != NULL) { QPainter painter(this); painter.setRenderHint(QPainter::SmoothPixmapTransform); if (!drawingPaused) { PauseTask(task); } painter.drawImage(fractalQImage->rect(), *fractalQImage, fractalQImage->rect()); if (!drawingPaused) { ResumeTask(task); } } } QSize FractalExplorer::sizeHint() const { if (fractalQImage == NULL) { return QSize(0, 0); } else { return fractalQImage->size(); } } void FractalExplorer::reInitFractal() { Fractal newFractal; InitFractal2(&newFractal, fractal.fractalFormula, fractal.p, fractal.c, fractal.centerX, fractal.centerY, fractal.spanX, fractal.spanY, fractal.escapeRadius, fractal.maxIter); Fractal oldFractal = fractal; fractal = newFractal; FreeFractal(oldFractal); } void FractalExplorer::reInitRenderingParameters() { InitRenderingParameters(&render, render.bytesPerComponent, render.spaceColor, render.iterationCount, render.coloringMethod, render.addendFunction, render.stripeDensity, render.interpolationMethod, render.transferFunction, render.multiplier, render.offset, render.gradient); } /* Assumes that action is finished.*/ void FractalExplorer::launchFractalDrawing() { /* Free previous action. Safe even for first launching * because action has been initialized to doNothingAction(). */ FreeTask(task); redrawFractal = false; lastActionType = A_FractalDrawing; task = CreateDrawFractalTask(&fractalImage, &fractal, &render, solidGuessing ? quadInterpolationSize : 1, colorDissimilarityThreshold, floatPrecision, pCache, threads->N); LaunchTask(task, threads); if (drawingPaused) { PauseTask(task); } } /* Assumes that action is finished.*/ void FractalExplorer::launchFractalAntiAliasing() { FreeTask(task); lastActionType = A_FractalAntiAliasing; task = CreateAntiAliaseFractalTask(&fractalImage, &fractal, &render, currentAntiAliasingSize, adaptiveAAMThreshold, floatPrecision, NULL, threads->N); LaunchTask(task, threads); if (drawingPaused) { PauseTask(task); } } int FractalExplorer::cancelActionIfNotFinished() { int finished = TaskIsFinished(task); if (!finished) { CancelTask(task); if (drawingPaused) { ResumeTask(task); } int unused = GetTaskResult(task); UNUSED(unused); } return finished; } void FractalExplorer::onTimeout() { bool updateNeeded = true; if (redrawFractal) { cancelActionIfNotFinished(); launchFractalDrawing(); } else { if (TaskIsFinished(task) && GetTaskResult(task) == 0) { if (lastActionType == A_FractalDrawing) { currentAntiAliasingSize = minAntiAliasingSize; launchFractalAntiAliasing(); } else if (currentAntiAliasingSize < maxAntiAliasingSize) { currentAntiAliasingSize += antiAliasingSizeIteration; if (currentAntiAliasingSize > maxAntiAliasingSize) { currentAntiAliasingSize = maxAntiAliasingSize; } launchFractalAntiAliasing(); } else { updateNeeded = false; } } } if (updateNeeded) { update(); } } int FractalExplorer::stopDrawing() { return cancelActionIfNotFinished(); } void FractalExplorer::pauseDrawing() { drawingPaused = true; PauseTask(task); } void FractalExplorer::resumeDrawing() { drawingPaused = false; ResumeTask(task); } void FractalExplorer::refresh() { redrawFractal = true; update(); } void FractalExplorer::moveFractal(const mpfr_t dx, const mpfr_t dy, bool emitFractalChanged) { cancelActionIfNotFinished(); mpfr_t absdx, absdy; mpfr_init(absdx); mpfr_init(absdy); mpfr_abs(absdx, dx, MPFR_RNDN); mpfr_abs(absdy, dy, MPFR_RNDN); if (mpfr_cmp_ui(fractal.spanX, 0) == 0 || mpfr_cmp_ui(fractal.spanY, 0) == 0 || mpfr_cmp(absdx, fractal.spanX) >= 0 || mpfr_cmp(absdy, fractal.spanY) >= 0) { fractalQImage->fill(0); } else { QImage copiedImage(fractalQImage->copy()); fractalQImage->fill(0); QPainter painter(fractalQImage); painter.setRenderHint(QPainter::SmoothPixmapTransform); mpfr_t imgdx, imgdy; mpfr_init(imgdx); mpfr_init(imgdy); mpfr_div(imgdx, dx, fractal.spanX, MPFR_RNDN); mpfr_mul_ui(imgdx, imgdx, fractalQImage->width(), MPFR_RNDN); mpfr_div(imgdy, dy, fractal.spanY, MPFR_RNDN); mpfr_mul_ui(imgdy, imgdy, fractalQImage->height(), MPFR_RNDN); long double ddx = mpfr_get_ld(imgdx, MPFR_RNDN); long double ddy = mpfr_get_ld(imgdy, MPFR_RNDN); QRectF srcRect = QRectF(std::max((long double)0, ddx), std::max((long double)0, ddy), fractalImage.width-fabsl(ddx), fractalImage.height-fabsl(ddy)); QRectF dstRect = QRectF(std::max((long double)0, -ddx), std::max((long double)0, -ddy), fractalImage.width-fabsl(ddx), fractalImage.height-fabsl(ddy)); painter.drawImage(dstRect, copiedImage, srcRect); mpfr_clear(imgdx); mpfr_clear(imgdy); } mpfr_clear(absdx); mpfr_clear(absdy); mpfr_add(fractal.centerX, fractal.centerX, dx, MPFR_RNDN); mpfr_add(fractal.centerY, fractal.centerY, dy, MPFR_RNDN); //fractal.centerX += dx; //fractal.centerY += dy; reInitFractal(); if (emitFractalChanged) { emit fractalChanged(fractal); } refresh(); } void FractalExplorer::moveLeftFractal() { mpfr_t dx, tmp; mpfr_init(dx); mpfr_init(tmp); if (mpfr_cmp_ui(fractal.spanX, 0) == 0) { mpfr_set_ld(dx, -MIN_SINGLE_STEP, MPFR_RNDN); } else { /* We use modf to have a multiple of image width, * so that the temporary qimage matches the * fractal image that will be computed exactly. */ mpfr_set_ld(tmp, -0.2 * fractalImage.width, MPFR_RNDN); mpfr_modf(dx, tmp, tmp, MPFR_RNDN); mpfr_mul(dx, dx, fractal.spanX, MPFR_RNDN); mpfr_div_ui(dx, dx, fractalImage.width, MPFR_RNDN); } mpfr_set_ui(tmp, 0, MPFR_RNDN); moveFractal(dx, tmp, true); mpfr_clear(dx); mpfr_clear(tmp); } void FractalExplorer::moveRightFractal() { mpfr_t dx, tmp; mpfr_init(dx); mpfr_init(tmp); if (mpfr_cmp_ui(fractal.spanX, 0) == 0) { mpfr_set_ld(dx, MIN_SINGLE_STEP, MPFR_RNDN); } else { mpfr_set_ld(tmp, 0.2 * fractalImage.width, MPFR_RNDN); mpfr_modf(dx, tmp, tmp, MPFR_RNDN); mpfr_mul(dx, dx, fractal.spanX, MPFR_RNDN); mpfr_div_ui(dx, dx, fractalImage.width, MPFR_RNDN); } mpfr_set_ui(tmp, 0, MPFR_RNDN); moveFractal(dx, tmp, true); mpfr_clear(dx); mpfr_clear(tmp); } void FractalExplorer::moveUpFractal() { mpfr_t dy, tmp; mpfr_init(dy); mpfr_init(tmp); if (mpfr_cmp_ui(fractal.spanY,0) == 0) { mpfr_set_ld(dy, -MIN_SINGLE_STEP, MPFR_RNDN); } else { mpfr_set_ld(tmp, -0.2 * fractalImage.height, MPFR_RNDN); mpfr_modf(dy, tmp, tmp, MPFR_RNDN); mpfr_mul(dy, dy, fractal.spanY, MPFR_RNDN); mpfr_div_ui(dy, dy, fractalImage.height, MPFR_RNDN); } mpfr_set_ui(tmp, 0, MPFR_RNDN); moveFractal(tmp, dy, true); mpfr_clear(dy); mpfr_clear(tmp); } void FractalExplorer::moveDownFractal() { mpfr_t dy, tmp; mpfr_init(dy); mpfr_init(tmp); if (mpfr_cmp_ui(fractal.spanY,0) == 0) { mpfr_set_ld(dy, MIN_SINGLE_STEP, MPFR_RNDN); } else { mpfr_set_ld(tmp, 0.2 * fractalImage.height, MPFR_RNDN); mpfr_modf(dy, tmp, tmp, MPFR_RNDN); mpfr_mul(dy, dy, fractal.spanY, MPFR_RNDN); mpfr_div_ui(dy, dy, fractalImage.height, MPFR_RNDN); } mpfr_set_ui(tmp, 0, MPFR_RNDN); moveFractal(tmp, dy, true); mpfr_clear(dy); mpfr_clear(tmp); } void FractalExplorer::zoomInFractal(const mpfr_t newSpanX, const mpfr_t zoomCenterX, const mpfr_t zoomCenterY, bool emitFractalChanged) { cancelActionIfNotFinished(); if (mpfr_cmp_ui(newSpanX, 0) == 0) { fractalQImage->fill(0); mpfr_set_ui(fractal.spanX, 0, MPFR_RNDN); mpfr_set_ui(fractal.spanY, 0, MPFR_RNDN); } else { mpfr_t newSpanY, newCenterX, newCenterY, ratioSpanX; mpfr_init(newSpanY); mpfr_init(newCenterX); mpfr_init(newCenterY); mpfr_init(ratioSpanX); mpfr_div(ratioSpanX, newSpanX, fractal.spanX, MPFR_RNDN); mpfr_mul_ui(newSpanY, newSpanX, fractalImage.height, MPFR_RNDN); mpfr_div_ui(newSpanY, newSpanY, fractalImage.width, MPFR_RNDN); mpfr_sub(newCenterX, fractal.centerX, zoomCenterX, MPFR_RNDN); mpfr_mul(newCenterX, newCenterX, ratioSpanX, MPFR_RNDN); mpfr_add(newCenterX, newCenterX, zoomCenterX, MPFR_RNDN); mpfr_sub(newCenterY, fractal.centerY, zoomCenterY, MPFR_RNDN); mpfr_mul(newCenterY, newCenterY, newSpanY, MPFR_RNDN); mpfr_div(newCenterY, newCenterY, fractal.spanY, MPFR_RNDN); mpfr_add(newCenterY, newCenterY, zoomCenterY, MPFR_RNDN); QImage copiedImage(fractalQImage->copy()); fractalQImage->fill(0); QPainter painter(fractalQImage); painter.setRenderHint(QPainter::SmoothPixmapTransform); QRect dstRect(fractalQImage->rect()); QRectF srcRect(0, 0, dstRect.width() * mpfr_get_ld(ratioSpanX,MPFR_RNDN), dstRect.height() * mpfr_get_ld(ratioSpanX,MPFR_RNDN)); mpfr_t srcRectCenterX, srcRectCenterY; mpfr_init(srcRectCenterX); mpfr_init(srcRectCenterY); mpfr_sub(srcRectCenterX, newCenterX, fractal.x1, MPFR_RNDN); mpfr_div(srcRectCenterX, srcRectCenterX, fractal.spanX, MPFR_RNDN); mpfr_mul_ui(srcRectCenterX, srcRectCenterX, fractalQImage->width(), MPFR_RNDN); mpfr_sub(srcRectCenterY, newCenterY, fractal.y1, MPFR_RNDN); mpfr_div(srcRectCenterY, srcRectCenterY, fractal.spanY, MPFR_RNDN); mpfr_mul_ui(srcRectCenterY, srcRectCenterY, fractalQImage->height(), MPFR_RNDN); srcRect.moveCenter(QPointF(mpfr_get_ld(srcRectCenterX, MPFR_RNDN), mpfr_get_ld(srcRectCenterY, MPFR_RNDN))); painter.drawImage(dstRect, copiedImage, srcRect); mpfr_set(fractal.centerX, newCenterX, MPFR_RNDN); mpfr_set(fractal.centerY, newCenterY, MPFR_RNDN); mpfr_set(fractal.spanX, newSpanX, MPFR_RNDN); mpfr_set(fractal.spanY, newSpanY, MPFR_RNDN); mpfr_clear(newSpanY); mpfr_clear(newCenterX); mpfr_clear(newCenterY); mpfr_clear(ratioSpanX); mpfr_clear(srcRectCenterX); mpfr_clear(srcRectCenterY); } reInitFractal(); if (emitFractalChanged) { emit fractalChanged(fractal); } refresh(); } void FractalExplorer::zoomOutFractal(const mpfr_t newSpanX, const mpfr_t zoomCenterX, const mpfr_t zoomCenterY, bool emitFractalChanged) { cancelActionIfNotFinished(); if (mpfr_cmp_ui(newSpanX,0) == 0) { fractalQImage->fill(0); mpfr_set_ui(fractal.spanX, 0, MPFR_RNDN); mpfr_set_ui(fractal.spanY, 0, MPFR_RNDN); } else { mpfr_t newSpanY, newCenterX, newCenterY, ratioSpanX; mpfr_init(newSpanY); mpfr_init(newCenterX); mpfr_init(newCenterY); mpfr_init(ratioSpanX); mpfr_div(ratioSpanX, newSpanX, fractal.spanX, MPFR_RNDN); mpfr_mul_ui(newSpanY, newSpanX, fractalImage.height, MPFR_RNDN); mpfr_div_ui(newSpanY, newSpanY, fractalImage.width, MPFR_RNDN); if (mpfr_cmp_ui(fractal.spanX,0) == 0 || mpfr_cmp_ui(fractal.spanY,0) == 0) { mpfr_set(newCenterX, zoomCenterX, MPFR_RNDN); mpfr_set(newCenterY, zoomCenterY, MPFR_RNDN); } else { mpfr_sub(newCenterX, fractal.centerX, zoomCenterX, MPFR_RNDN); mpfr_mul(newCenterX, newCenterX, ratioSpanX, MPFR_RNDN); mpfr_add(newCenterX, newCenterX, zoomCenterX, MPFR_RNDN); mpfr_sub(newCenterY, fractal.centerY, zoomCenterY, MPFR_RNDN); mpfr_mul(newCenterY, newCenterY, newSpanY, MPFR_RNDN); mpfr_div(newCenterY, newCenterY, fractal.spanY, MPFR_RNDN); mpfr_add(newCenterY, newCenterY, zoomCenterY, MPFR_RNDN); } QImage copiedImage(fractalQImage->copy()); fractalQImage->fill(0); QPainter painter(fractalQImage); painter.setRenderHint(QPainter::SmoothPixmapTransform); QRect srcRect(fractalQImage->rect()); QRectF dstRect(0, 0, srcRect.width() / mpfr_get_ld(ratioSpanX, MPFR_RNDN), srcRect.height() / mpfr_get_ld(ratioSpanX, MPFR_RNDN)); mpfr_t dstRectCenterX, dstRectCenterY; mpfr_init(dstRectCenterX); mpfr_init(dstRectCenterY); mpfr_div_ui(dstRectCenterX, newSpanX, 2, MPFR_RNDN); mpfr_sub(dstRectCenterX, newCenterX, dstRectCenterX, MPFR_RNDN); mpfr_sub(dstRectCenterX, fractal.centerX, dstRectCenterX, MPFR_RNDN); mpfr_div(dstRectCenterX, dstRectCenterX, newSpanX, MPFR_RNDN); mpfr_mul_ui(dstRectCenterX, dstRectCenterX, srcRect.width(), MPFR_RNDN); mpfr_div_ui(dstRectCenterY, newSpanY, 2, MPFR_RNDN); mpfr_sub(dstRectCenterY, newCenterY, dstRectCenterY, MPFR_RNDN); mpfr_sub(dstRectCenterY, fractal.centerY, dstRectCenterY, MPFR_RNDN); mpfr_div(dstRectCenterY, dstRectCenterY, newSpanY, MPFR_RNDN); mpfr_mul_ui(dstRectCenterY, dstRectCenterY, srcRect.height(), MPFR_RNDN); dstRect.moveCenter(QPointF(mpfr_get_ld(dstRectCenterX, MPFR_RNDN), mpfr_get_ld(dstRectCenterY, MPFR_RNDN))); painter.drawImage(dstRect, copiedImage, srcRect); mpfr_set(fractal.centerX, newCenterX, MPFR_RNDN); mpfr_set(fractal.centerY, newCenterY, MPFR_RNDN); mpfr_set(fractal.spanX, newSpanX, MPFR_RNDN); mpfr_set(fractal.spanY, newSpanY, MPFR_RNDN); mpfr_clear(newSpanY); mpfr_clear(newCenterX); mpfr_clear(newCenterY); mpfr_clear(ratioSpanX); mpfr_clear(dstRectCenterX); mpfr_clear(dstRectCenterY); } reInitFractal(); if (emitFractalChanged) { emit fractalChanged(fractal); } refresh(); } void FractalExplorer::zoomInFractal() { mpfr_t newSpanX, tmp; mpfr_init(newSpanX); mpfr_init(tmp); if (mpfr_cmp_ui(fractal.spanX,0) == 0) { mpfr_set_ld(newSpanX, MIN_SINGLE_STEP, MPFR_RNDN); } else { mpfr_set_ld(tmp, (1 - 0.3) * fractalImage.width, MPFR_RNDN); mpfr_modf(newSpanX, tmp, tmp, MPFR_RNDN); mpfr_mul(newSpanX, newSpanX, fractal.spanX, MPFR_RNDN); mpfr_div_ui(newSpanX, newSpanX, fractalImage.width, MPFR_RNDN); } zoomInFractal(newSpanX, fractal.centerX, fractal.centerY, true); mpfr_clear(newSpanX); mpfr_clear(tmp); } void FractalExplorer::zoomOutFractal() { mpfr_t newSpanX, tmp; mpfr_init(newSpanX); mpfr_init(tmp); if (mpfr_cmp_ui(fractal.spanX,0) == 0) { mpfr_set_ld(newSpanX, MIN_SINGLE_STEP, MPFR_RNDN); } else { mpfr_set_ld(tmp, (1 + 0.3) * fractalImage.width, MPFR_RNDN); mpfr_modf(newSpanX, tmp, tmp, MPFR_RNDN); mpfr_mul(newSpanX, newSpanX, fractal.spanX, MPFR_RNDN); mpfr_div_ui(newSpanX, newSpanX, fractalImage.width, MPFR_RNDN); } zoomOutFractal(newSpanX, fractal.centerX, fractal.centerY, true); mpfr_clear(newSpanX); mpfr_clear(tmp); } void FractalExplorer::mousePressEvent(QMouseEvent *event) { if (fractalMoved) { emit fractalChanged(fractal); refresh(); } movingFractalDeferred = false; movingFractalRealTime = false; fractalMoved = false; QApplication::restoreOverrideCursor(); switch (event->button()) { case Qt::LeftButton: movingFractalDeferred = true; mpfr_set(fractalCenterXOnPress, fractal.centerX, MPFR_RNDN); mpfr_set(fractalCenterYOnPress, fractal.centerY, MPFR_RNDN); mousePosOnPress = event->localPos(); QApplication::setOverrideCursor(Qt::ClosedHandCursor); break; case Qt::MidButton: movingFractalRealTime = true; QApplication::setOverrideCursor(Qt::ClosedHandCursor); break; default: QLabel::mousePressEvent(event); } prevMousePos = event->localPos(); } void FractalExplorer::mouseReleaseEvent(QMouseEvent *event) { switch (event->button()) { case Qt::LeftButton: if (movingFractalDeferred) { if (fractalMoved) { emit fractalChanged(fractal); refresh(); } movingFractalDeferred = false; fractalMoved = false; QApplication::restoreOverrideCursor(); } break; case Qt::MidButton: if (movingFractalRealTime) { movingFractalRealTime = false; QApplication::restoreOverrideCursor(); } break; default: QLabel::mouseReleaseEvent(event); } } void FractalExplorer::mouseMoveEvent(QMouseEvent *event) { if (movingFractalDeferred) { if (!fractalMoved) { cancelActionIfNotFinished(); imageCopyOnPress = fractalQImage->copy(); } fractalMoved = true; QVector2D vect(event->localPos()-mousePosOnPress); mpfr_t dx, dy; mpfr_init(dx); mpfr_init(dy); mpfr_mul_d(dx, fractal.spanX, vect.x(), MPFR_RNDN); mpfr_div_ui(dx, dx, fractalImage.width, MPFR_RNDN); mpfr_mul_d(dy, fractal.spanY, vect.y(), MPFR_RNDN); mpfr_div_ui(dy, dy, fractalImage.height, MPFR_RNDN); fractalQImage->fill(0); QPainter painter(fractalQImage); painter.setRenderHint(QPainter::SmoothPixmapTransform); double ddx = vect.x(); double ddy = vect.y(); QRectF srcRect = QRectF(std::max((double)0, -ddx), std::max((double)0, -ddy), fractalImage.width - fabs(ddx), fractalImage.height - fabs(ddy)); QRectF dstRect = QRectF(std::max((double)0, ddx), std::max((double)0, ddy), fractalImage.width - fabs(ddx), fractalImage.height - fabs(ddy)); painter.drawImage(dstRect, imageCopyOnPress, srcRect); mpfr_sub(fractal.centerX, fractalCenterXOnPress, dx, MPFR_RNDN); mpfr_sub(fractal.centerY, fractalCenterYOnPress, dy, MPFR_RNDN); mpfr_clear(dx); mpfr_clear(dy); reInitFractal(); emit fractalChanged(fractal); } else if (movingFractalRealTime) { QVector2D vect(event->localPos()-prevMousePos); mpfr_t dx, dy; mpfr_init(dx); mpfr_init(dy); mpfr_mul_d(dx, fractal.spanX, -vect.x(), MPFR_RNDN); mpfr_div_ui(dx, dx, fractalImage.width, MPFR_RNDN); mpfr_mul_d(dy, fractal.spanY, -vect.y(), MPFR_RNDN); mpfr_div_ui(dy, dy, fractalImage.height, MPFR_RNDN); moveFractal(dx, dy, true); prevMousePos = event->localPos(); mpfr_clear(dx); mpfr_clear(dy); } else { QLabel::mouseMoveEvent(event); } update(); } static inline double signl(double x) { return (x > 0) ? 1 : -1; } void FractalExplorer::wheelEvent(QWheelEvent *event) { if (movingFractalDeferred) { if (fractalMoved) { emit fractalChanged(fractal); refresh(); } movingFractalDeferred = false; fractalMoved = false; QApplication::restoreOverrideCursor(); } double numDegrees = event->delta() / 8.; double numSteps = numDegrees / 15; if (event->orientation() == Qt::Vertical) { mpfr_t newSpanX; mpfr_init(newSpanX); if (mpfr_cmp_ui(fractal.spanX, 0) == 0) { mpfr_set_ld(newSpanX, MIN_SINGLE_STEP, MPFR_RNDN); } else { mpfr_mul_d(newSpanX, fractal.spanX, powl(1 - signl(numSteps)*0.3, fabsl(numSteps)), MPFR_RNDN); } mpfr_t zoomCenterX, zoomCenterY; mpfr_init(zoomCenterX); mpfr_init(zoomCenterY); if (mpfr_cmp_ui(fractal.spanX,0) == 0 || mpfr_cmp_ui(fractal.spanY,0) == 0) { mpfr_set(zoomCenterX, fractal.centerX, MPFR_RNDN); mpfr_set(zoomCenterY, fractal.centerY, MPFR_RNDN); } else { mpfr_mul_d(zoomCenterX, fractal.spanX, (event->x() + 0.5) / fractalImage.width, MPFR_RNDN); mpfr_add(zoomCenterX, zoomCenterX, fractal.x1, MPFR_RNDN); mpfr_mul_d(zoomCenterY, fractal.spanY, (event->y() + 0.5) / fractalImage.height, MPFR_RNDN); mpfr_add(zoomCenterY, zoomCenterY, fractal.y1, MPFR_RNDN); } if (numSteps > 0) { zoomInFractal(newSpanX, zoomCenterX, zoomCenterY, true); } else { zoomOutFractal(newSpanX, zoomCenterX, zoomCenterY, true); } mpfr_clear(newSpanX); mpfr_clear(zoomCenterX); mpfr_clear(zoomCenterY); } event->accept(); update(); } void FractalExplorer::setFractalFormula(int index) { cancelActionIfNotFinished(); fractal.fractalFormula = (FractalFormula)index; reInitFractal(); emit fractalChanged(fractal); refresh(); } void FractalExplorer::setPParam(const mpc_t *value) { cancelActionIfNotFinished(); mpc_set(fractal.p, *value, MPC_RNDNN); reInitFractal(); refresh(); } void FractalExplorer::setPParamRe(const mpfr_t *value) { cancelActionIfNotFinished(); mpfr_t im; mpfr_init(im); mpfr_set(im, mpc_imagref(fractal.p), MPFR_RNDN); mpc_set_fr_fr(fractal.p, *value, im, MPC_RNDNN); mpfr_clear(im); reInitFractal(); refresh(); } void FractalExplorer::setPParamIm(const mpfr_t *value) { cancelActionIfNotFinished(); mpfr_t re; mpfr_init(re); mpfr_set(re, mpc_realref(fractal.p), MPFR_RNDN); mpc_set_fr_fr(fractal.p, re, *value, MPC_RNDNN); mpfr_clear(re); reInitFractal(); refresh(); } void FractalExplorer::setCParamRe(const mpfr_t *value) { cancelActionIfNotFinished(); mpfr_t im; mpfr_init(im); mpfr_set(im, mpc_imagref(fractal.c), MPFR_RNDN); mpc_set_fr_fr(fractal.c, *value, im, MPC_RNDNN); mpfr_clear(im); reInitFractal(); refresh(); } void FractalExplorer::setCParamIm(const mpfr_t *value) { cancelActionIfNotFinished(); mpfr_t re; mpfr_init(re); mpfr_set(re, mpc_realref(fractal.c), MPFR_RNDN); mpc_set_fr_fr(fractal.c, re, *value, MPC_RNDNN); mpfr_clear(re); reInitFractal(); refresh(); } void FractalExplorer::setCenterX(const mpfr_t *value) { mpfr_t dx, dy; mpfr_init(dx); mpfr_init(dy); mpfr_sub(dx, *value, fractal.centerX, MPFR_RNDN); mpfr_set_ui(dy, 0, MPFR_RNDN); moveFractal(dx, dy); mpfr_clear(dx); mpfr_clear(dy); } void FractalExplorer::setCenterY(const mpfr_t *value) { mpfr_t dx, dy; mpfr_init(dx); mpfr_init(dy); mpfr_set_ui(dx, 0, MPFR_RNDN); mpfr_sub(dy, *value, fractal.centerY, MPFR_RNDN); moveFractal(dx, dy); mpfr_clear(dx); mpfr_clear(dy); } void FractalExplorer::setSpanX(const mpfr_t *value) { if (mpfr_cmp(*value, fractal.spanX) > 0) { /* Zoom out */ zoomOutFractal(*value, fractal.centerX, fractal.centerY); } else { /* Zoom in */ zoomInFractal(*value, fractal.centerX, fractal.centerY); } } void FractalExplorer::setBailoutRadius(double value) { cancelActionIfNotFinished(); fractal.escapeRadius = value; reInitFractal(); refresh(); } void FractalExplorer::setMaxIterations(int value) { cancelActionIfNotFinished(); fractal.maxIter = value; reInitFractal(); refresh(); } void FractalExplorer::setAddendFunction(int index) { cancelActionIfNotFinished(); render.addendFunction = (AddendFunction)index; reInitRenderingParameters(); refresh(); } void FractalExplorer::setStripeDensity(int value) { cancelActionIfNotFinished(); render.stripeDensity = value; reInitRenderingParameters(); refresh(); } void FractalExplorer::setColoringMethod(int index) { cancelActionIfNotFinished(); render.coloringMethod = (ColoringMethod)index; reInitRenderingParameters(); refresh(); } void FractalExplorer::setIterationCount(int index) { cancelActionIfNotFinished(); render.iterationCount = (IterationCount)index; reInitRenderingParameters(); refresh(); } void FractalExplorer::setInterpolationMethod(int index) { cancelActionIfNotFinished(); render.interpolationMethod = (InterpolationMethod)index; reInitRenderingParameters(); refresh(); } void FractalExplorer::setTransferFunction(int index) { cancelActionIfNotFinished(); render.transferFunction = (TransferFunction)index; reInitRenderingParameters(); refresh(); } void FractalExplorer::setColorScaling(double value) { cancelActionIfNotFinished(); render.multiplier = value; reInitRenderingParameters(); refresh(); } void FractalExplorer::setColorOffset(double value) { cancelActionIfNotFinished(); render.offset = value; reInitRenderingParameters(); refresh(); } void FractalExplorer::setSpaceColor(const QColor &color) { cancelActionIfNotFinished(); render.spaceColor = ColorFromRGB(1, (uint16_t)color.red(), (uint16_t)color.green(), (uint16_t)color.blue()); reInitRenderingParameters(); refresh(); } inline static bool pos_less_than(const QGradientStop &s1, const QGradientStop &s2) { return s1.first < s2.first; } void FractalExplorer::setGradient(const QGradientStops &gradientStops) { if (gradientStops.size() < 2) { /* Emit signal to be sure that fractal explorer's gradient * matches rendering widget's gradient box. */ emit renderingParametersChanged(render); return; } cancelActionIfNotFinished(); /* First, sort gradient stops.*/ QGradientStops sortedGradientStops(gradientStops); qSort(sortedGradientStops.begin(), sortedGradientStops.end(), pos_less_than); /* Now create well formed gradient stops, i.e. first gradient * stop position must be 0, last must be 1, and positions * must be strictly increasing ("duplicates" are skipped). */ bool wellFormed = 1; QGradientStops wellFormedGradientStops; /* First position must be 0.*/ if (sortedGradientStops[0].first != 0) { wellFormed = 0; } wellFormedGradientStops << QPair(0, sortedGradientStops[0].second); for (int i = 1; i < sortedGradientStops.size(); ++i) { /* Positions should be strictly increasing.*/ if (sortedGradientStops[i].first <= wellFormedGradientStops[i-1].first) { wellFormed = 0; continue; } wellFormedGradientStops << sortedGradientStops[i]; } /* Last position must be 1.*/ if (wellFormedGradientStops.last().first != 1) { wellFormedGradientStops.last() = QPair(1, wellFormedGradientStops.last().second); wellFormed = 0; } /* Now gradient FractalNow gradient from well formed gradient.*/ double positionStop[wellFormedGradientStops.size()]; Color colorStop[wellFormedGradientStops.size()]; QGradientStop currentStop; for (int i = 0; i < wellFormedGradientStops.size(); ++i) { currentStop = wellFormedGradientStops[i]; positionStop[i] = currentStop.first; colorStop[i] = ColorFromUint32(currentStop.second.rgb()); } /* Replace old gradient.*/ Gradient oldGradient = render.gradient; GenerateGradient(&render.gradient, wellFormedGradientStops.size(), positionStop, colorStop, DEFAULT_GRADIENT_SIZE); FreeGradient(oldGradient); reInitRenderingParameters(); refresh(); if (!wellFormed) { emit renderingParametersChanged(render); } } void FractalExplorer::setFloatPrecision(int index) { cancelActionIfNotFinished(); floatPrecision = (FloatPrecision)index; refresh(); } void FractalExplorer::contextMenuEvent(QContextMenuEvent *event) { QMenu menu(this); menu.addAction(restoreInitialStateAction); menu.addSeparator(); menu.addAction(stopDrawingAction); menu.addAction(refreshAction); menu.addSeparator(); menu.addAction(zoomInAction); menu.addAction(zoomOutAction); menu.addSeparator(); menu.addAction(moveLeftAction); menu.addAction(moveRightAction); menu.addAction(moveUpAction); menu.addAction(moveDownAction); QAction *action = menu.exec(event->globalPos()); UNUSED(action); } fractalnow-0.8.2/lib/include/fractal_coloring.h000664 001750 001750 00000026176 13175115345 021500 0ustar00mpegmpeg000000 000000 /* * fractal_coloring.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal_coloring.h * \brief Header file related to fractal coloring. * * Contains coloring methods and interpolation. * * \author Marc Pegon */ #ifndef __FRACTAL_COLORING_H__ #define __FRACTAL_COLORING_H__ #include "float_precision.h" #include "fractal_addend_function.h" #include "fractal_iteration_count.h" #include #ifdef __cplusplus extern "C" { #endif /** * \enum e_ColoringMethod * \brief Possible coloring methods. * * For iteration count coloring method, fractal value (before applying transfer * function and multiplier) is simply the result of iteration count function.\n * For average sums coloring method, fractal value is computed by interpolation * function thanks to addend function and smooth iteration count. * * See addend function and interation count headers for more details. * \see fractal_addend_function.h * \see fractal_counting_function.h */ /** * \typedef ColoringMethod * \brief Convenient typedef for enum ColoringMethod. */ typedef enum e_ColoringMethod { CM_ITERATIONCOUNT = 0, /*SN_IM[0]);\ ENGINE_INIT_VAR_##addend(1,fprec) #define ENGINE_CLEAR_VAR_IM_NONE(addend,fprec) \ clearF(fprec, data->SN_IM[0]);\ ENGINE_CLEAR_VAR_##addend(1,fprec) #define LOOP_INIT_IM_NONE(addend,fprec) \ LOOP_INIT_##addend(1,fprec) #define LOOP_ITERATION_IM_NONE(addend,fprec) \ LOOP_ITERATION_##addend(1,fprec) #define LOOP_END_IM_NONE(addend,fprec) \ LOOP_END_##addend(1,fprec)\ assignF(fprec,data->res,data->SN_IM[0]); /*********************************************************/ /************************IM_LINEAR************************/ #define ENGINE_DECL_VAR_IM_LINEAR(addend,fprec) \ ENGINE_DECL_VAR_IC_SMOOTH(fprec)\ FLOATTYPE(fprec) tmp_IM;\ FLOATTYPE(fprec) SN_IM[2];\ ENGINE_DECL_VAR_##addend(2,fprec) #define ENGINE_INIT_VAR_IM_LINEAR(addend,fprec) \ ENGINE_INIT_VAR_IC_SMOOTH(fprec)\ initF(fprec, data->tmp_IM);\ initF(fprec, data->SN_IM[0]);\ initF(fprec, data->SN_IM[1]);\ ENGINE_INIT_VAR_##addend(2,fprec) #define ENGINE_CLEAR_VAR_IM_LINEAR(addend,fprec) \ ENGINE_CLEAR_VAR_IC_SMOOTH(fprec)\ clearF(fprec, data->tmp_IM);\ clearF(fprec, data->SN_IM[0]);\ clearF(fprec, data->SN_IM[1]);\ ENGINE_CLEAR_VAR_##addend(2,fprec) #define LOOP_INIT_IM_LINEAR(addend,fprec) \ LOOP_INIT_##addend(2,fprec) #define LOOP_ITERATION_IM_LINEAR(addend,fprec) \ LOOP_ITERATION_##addend(2,fprec) #define LOOP_END_IM_LINEAR(addend,fprec) \ LOOP_END_##addend(2,fprec)\ COMPUTE_IC_SMOOTH(fprec)\ modfF(fprec, data->tmp_IM, data->res, data->res);\ sub_uiF(fprec, data->tmp_IM, data->res, 1);\ mulF(fprec, data->tmp_IM, data->tmp_IM, data->SN_IM[1]);\ mulF(fprec, data->res, data->res, data->SN_IM[0]);\ subF(fprec, data->res, data->res, data->tmp_IM); /*********************************************************/ /************************IM_SPLINE************************/ #define ENGINE_DECL_VAR_IM_SPLINE(addend,fprec) \ ENGINE_DECL_VAR_IC_SMOOTH(fprec)\ FLOATTYPE(fprec) tmp_IM;\ FLOATTYPE(fprec) d1_IM;\ FLOATTYPE(fprec) d2_IM;\ FLOATTYPE(fprec) d3_IM;\ FLOATTYPE(fprec) s1_IM;\ FLOATTYPE(fprec) s2_IM;\ FLOATTYPE(fprec) s3_IM;\ FLOATTYPE(fprec) SN_IM[4];\ ENGINE_DECL_VAR_##addend(4,fprec) #define ENGINE_INIT_VAR_IM_SPLINE(addend,fprec) \ ENGINE_INIT_VAR_IC_SMOOTH(fprec)\ initF(fprec,data->tmp_IM);\ initF(fprec,data->d1_IM);\ initF(fprec,data->d2_IM);\ initF(fprec,data->d3_IM);\ initF(fprec,data->s1_IM);\ initF(fprec,data->s2_IM);\ initF(fprec,data->s3_IM);\ for (uint_fast32_t i = 0; i < 4; ++i) {\ initF(fprec,data->SN_IM[i]);\ }\ ENGINE_INIT_VAR_##addend(4,fprec) #define ENGINE_CLEAR_VAR_IM_SPLINE(addend,fprec) \ ENGINE_CLEAR_VAR_IC_SMOOTH(fprec)\ clearF(fprec,data->tmp_IM);\ clearF(fprec,data->d1_IM);\ clearF(fprec,data->d2_IM);\ clearF(fprec,data->d3_IM);\ clearF(fprec,data->s1_IM);\ clearF(fprec,data->s2_IM);\ clearF(fprec,data->s3_IM);\ for (uint_fast32_t i = 0; i < 4; ++i) {\ clearF(fprec,data->SN_IM[i]);\ }\ ENGINE_CLEAR_VAR_##addend(4,fprec) #define LOOP_INIT_IM_SPLINE(addend,fprec) \ LOOP_INIT_##addend(4,fprec) #define LOOP_ITERATION_IM_SPLINE(addend,fprec) \ LOOP_ITERATION_##addend(4,fprec) #define LOOP_END_IM_SPLINE(addend,fprec) \ LOOP_END_##addend(4,fprec)\ COMPUTE_IC_SMOOTH(fprec)\ modfF(fprec,data->tmp_IM,data->d1_IM,data->res);\ mulF(fprec,data->d2_IM,data->d1_IM,data->d1_IM);\ mulF(fprec,data->d3_IM,data->d1_IM,data->d2_IM);\ \ /* Compute s1 */\ mul_uiF(fprec,data->tmp_IM,data->d2_IM,4);\ addF(fprec,data->s1_IM,data->d1_IM,data->tmp_IM);\ mul_uiF(fprec,data->tmp_IM,data->d3_IM,3);\ subF(fprec,data->s1_IM,data->s1_IM,data->tmp_IM);\ mulF(fprec,data->s1_IM,data->s1_IM,data->SN_IM[1]);\ \ /* Compute s2 */\ mul_uiF(fprec,data->s2_IM,data->d3_IM,3);\ mul_uiF(fprec,data->tmp_IM,data->d2_IM,5);\ subF(fprec,data->s2_IM,data->s2_IM,data->tmp_IM);\ add_uiF(fprec,data->s2_IM,data->s2_IM,2);\ mulF(fprec,data->s2_IM,data->s2_IM,data->SN_IM[2]);\ \ /* Compute s3 */\ mul_uiF(fprec,data->s3_IM,data->d2_IM,2);\ subF(fprec,data->s3_IM,data->s3_IM,data->d1_IM);\ subF(fprec,data->s3_IM,data->s3_IM,data->d3_IM);\ mulF(fprec,data->s3_IM,data->s3_IM,data->SN_IM[3]);\ \ /* Compute res */\ subF(fprec,data->res,data->d3_IM,data->d2_IM);\ mulF(fprec,data->res,data->res,data->SN_IM[0]);\ addF(fprec,data->res,data->res,data->s1_IM);\ addF(fprec,data->res,data->res,data->s2_IM);\ addF(fprec,data->res,data->res,data->s3_IM);\ div_uiF(fprec,data->res,data->res,2); /*********************************************************/ #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/gui/icons/icon.xpm000664 001750 001750 00000015504 13175112471 017171 0ustar00mpegmpeg000000 000000 /* XPM */ static char * icon_xpm[] = { "32 32 297 2", " c None", ". c #8D8DFF", "+ c #8989FF", "@ c #7C7CFF", "# c #7B7BFF", "$ c #7E7EFF", "% c #8181FF", "& c #8C8CFF", "* c #9898FF", "= c #9292FF", "- c #8787FF", "; c #8888FF", "> c #9595FF", ", c #A7A7FE", "' c #9B9BFF", ") c #8F8FFF", "! c #9090FF", "~ c #8E8EFF", "{ c #A1A1FE", "] c #8A8AFF", "^ c #8383FF", "/ c #8282FF", "( c #8585FF", "_ c #9696FE", ": c #9E9EFE", "< c #8080FF", "[ c #7F7FFF", "} c #8484FF", "| c #A4A4FE", "1 c #8B8BFF", "2 c #9191FF", "3 c #9494FF", "4 c #A2A2FF", "5 c #9D9DFF", "6 c #9797FF", "7 c #8686FF", "8 c #9393FF", "9 c #9B9BFE", "0 c #9A9AFF", "a c #A5A5FE", "b c #A8A8FF", "c c #ACACFE", "d c #9F9FFF", "e c #A6A6FF", "f c #9C9CFF", "g c #A5A5FF", "h c #A3A3FF", "i c #9696FF", "j c #9D9DFE", "k c #9C9CFE", "l c #A6A6FE", "m c #A0A0FF", "n c #A7A7FF", "o c #A1A1FF", "p c #ADADFF", "q c #BBBBFE", "r c #AFAFFF", "s c #B4B4FE", "t c #ABABFF", "u c #B6B6FE", "v c #9F9FFE", "w c #B2B2FD", "x c #7D7DFF", "y c #A0A0FE", "z c #B1B1FE", "A c #B1B1FF", "B c #B2B2FF", "C c #C3C3FE", "D c #D0D0FA", "E c #CECEFD", "F c #C2C2FF", "G c #AAAAFF", "H c #ABABFE", "I c #A9A9FE", "J c #B2B2FE", "K c #B5B5FE", "L c #A9A9FF", "M c #C1C1FE", "N c #D7D7FF", "O c #F4F0D0", "P c #F4EFC3", "Q c #E6E5F1", "R c #CBCBFD", "S c #BDBDFE", "T c #A4A4FF", "U c #ADADFE", "V c #AAAAFE", "W c #9999FF", "X c #B3B3FE", "Y c #C0C0FE", "Z c #B6B6FF", "` c #BEBEFE", " . c #CACAFE", ".. c #D9D9FE", "+. c #EBEBFC", "@. c #FDFAC7", "#. c #F5DA5F", "$. c #FAEFA4", "%. c #E6E7FA", "&. c #CECEFE", "*. c #BBBBFF", "=. c #B4B4FF", "-. c #BCBCFE", ";. c #9E9EFF", ">. c #ACACFF", ",. c #B3B3FF", "'. c #C2C2FE", "). c #C9C9FE", "!. c #DADAFE", "~. c #EBEBFD", "{. c #FAF6D9", "]. c #E1C670", "^. c #8E672F", "/. c #DBC06A", "(. c #F7F4E1", "_. c #E0E0FF", ":. c #C6C6FE", "<. c #B5B5FF", "[. c #B9B9FF", "}. c #C8C8FE", "|. c #E6E6FA", "1. c #F6F6F0", "2. c #FDFDE8", "3. c #FFFAAE", "4. c #836530", "5. c #040003", "6. c #7E6230", "7. c #FFF9B8", "8. c #F8F8F2", "9. c #EBECFA", "0. c #DBDBFA", "a. c #C1C1FF", "b. c #BFBFFE", "c. c #BABAFF", "d. c #CDCDFE", "e. c #DBDBFE", "f. c #EAEAFD", "g. c #F6EBC0", "h. c #DDBC72", "i. c #E3D37B", "j. c #B6A250", "k. c #634A1B", "l. c #040005", "m. c #5C461B", "n. c #B4A051", "o. c #E5D793", "p. c #F8EDA7", "q. c #F2E3AD", "r. c #D7D7FC", "s. c #A2A2FE", "t. c #CECEFF", "u. c #D4D4FE", "v. c #DEDEFE", "w. c #E1E1FE", "x. c #EEEEFC", "y. c #FAFBEF", "z. c #FAEF9D", "A. c #775628", "B. c #3C2912", "C. c #0F0805", "D. c #030101", "E. c #010101", "F. c #020101", "G. c #0B0504", "H. c #53401A", "I. c #6E5226", "J. c #DDC27C", "K. c #E5E5F9", "L. c #C3C4FF", "M. c #B9B9FE", "N. c #C5C5FE", "O. c #DADAFC", "P. c #EFEDE6", "Q. c #F2F3F4", "R. c #F5F6F4", "S. c #F9F9F2", "T. c #FDFDED", "U. c #FBF5BC", "V. c #AD904C", "W. c #31230F", "X. c #000000", "Y. c #E1D489", "Z. c #F0EFEE", "`. c #CDCDFF", " + c #B7B7FF", ".+ c #AFAFFE", "++ c #BCBCFF", "@+ c #D5D5FE", "#+ c #EFEFF6", "$+ c #FBEF95", "%+ c #F8EA95", "&+ c #F8E78D", "*+ c #F7E998", "=+ c #FFFFB5", "-+ c #E7DC7E", ";+ c #443018", ">+ c #070402", ",+ c #806834", "'+ c #EEE1C2", ")+ c #D1D2FF", "!+ c #B8B8FF", "~+ c #CBCBFE", "{+ c #ECECFB", "]+ c #FBFCEA", "^+ c #FCF18C", "/+ c #9D742F", "(+ c #6A4B20", "_+ c #634523", ":+ c #BBA547", "<+ c #B6A435", "[+ c #0C0606", "}+ c #64532A", "|+ c #F1EAD0", "1+ c #D5D6FF", "2+ c #C8C8FF", "3+ c #DBDCFE", "4+ c #E6E6FD", "5+ c #F1F1FB", "6+ c #FCFBDC", "7+ c #FFF492", "8+ c #D3B44B", "9+ c #2C1B0F", "0+ c #201509", "a+ c #563212", "b+ c #010001", "c+ c #786944", "d+ c #F2EEE6", "e+ c #B0B0FF", "f+ c #D1D1F9", "g+ c #EEEEE8", "h+ c #F2EEBE", "i+ c #F9F4B6", "j+ c #FEF9AE", "k+ c #FAE77B", "l+ c #A27A32", "m+ c #3F2715", "n+ c #030102", "o+ c #060308", "p+ c #2D2710", "q+ c #D4CD99", "r+ c #F1F1FA", "s+ c #D2D2FE", "t+ c #B8B8FE", "u+ c #B0B0FE", "v+ c #D1D0F9", "w+ c #F2EEBF", "x+ c #F9F5B6", "y+ c #A27B32", "z+ c #402715", "A+ c #070308", "B+ c #2C2710", "C+ c #D3CC99", "D+ c #C7C7FF", "E+ c #D3B54B", "F+ c #211509", "G+ c #573212", "H+ c #786943", "I+ c #F2EEE5", "J+ c #ECECFC", "K+ c #9E742F", "L+ c #6B4C20", "M+ c #644623", "N+ c #BCA648", "O+ c #F9EA95", "P+ c #F8E88D", "Q+ c #F7E999", "R+ c #FFFFB6", "S+ c #453018", "T+ c #816934", "U+ c #EEE2C2", "V+ c #F2F3F5", "W+ c #F5F5F4", "X+ c #F9F9F3", "Y+ c #FDFDEE", "Z+ c #AE904C", "`+ c #CDCEFF", " @ c #3C2A12", ".@ c #100805", "+@ c #0C0504", "@@ c #53411B", "#@ c #6F5226", "$@ c #C3C3FF", "%@ c #DEBC72", "&@ c #E3D47B", "*@ c #B7A350", "=@ c #634B1B", "-@ c #5D471B", ";@ c #B5A152", ">@ c #F8EDA8", ",@ c #E1C770", "'@ c #8F682F", ")@ c #DBC16B", "!@ c #EAEBFD", "~@ c #F6DA60", "{@ c #F4EFC4", "]@ c #AEAEFF", "^@ c #A8A8FE", " . + @ # # @ $ % & * = + - ; & > , ' ) ! . ~ { ' ] ^ / - / ( ", "_ : ; < $ [ [ < } ! | ' & 1 2 2 3 , 4 > 5 > 6 | = + 7 - 8 ] ) 9 ", "& > 6 - ( . ( ^ 7 & 0 a 3 ! 5 5 * b c d e f g h = 2 1 1 i j k . ", "[ 7 6 i ~ i + - ; 1 3 l m i 5 n o p q r s t u h ' v 2 2 { w ' & ", "x / 1 y , 6 & 1 2 = 8 4 c o m z A B C D E F q G H d 6 d I d 3 8 ", "$ + 8 y J 4 = ! 0 m * m K u L A M C N O P Q R S s T n U 5 2 ] 7 ", "[ - ) = m V f > W n o T X Y Z ` ...+.@.#.$.%.&.*.=.-.e 6 = & 7 ", "< } ; & 8 h U d ;.G s >.,.'.).&.!.~.{.].^./.(._.&.:.<.g m m ! + ", "( 7 ] ! 8 ' U K L >.S [.'.}.!.|.1.2.3.4.5.6.7.8.9.0.a.K L 0 = 2 ", "8 1 ~ ;.5 f t b.Z c.C d.&.e.f.g.h.i.j.k.l.m.n.o.p.q.r.[.b o o a ", "s.* = 0 b L t [.).t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.q K , ' ", "0 a h d b M.[.N.O.P.Q.R.S.T.U.V.W.X.X.X.X.X.X.X.W.Y.Z.`. +b 0 8 ", "! 0 .+s r ++d.@+#+$+%+&+*+=+-+;+X.X.X.X.X.X.X.X.>+,+'+)+!+t 4 m ", "' ;.L S '.~+..{+]+^+/+(+_+:+<+[+X.X.X.X.X.X.X.X.X.}+|+1+` J h ' ", "0 b +2+3+4+5+6+7+8+9+X.X.0+a+b+X.X.X.X.X.X.X.X.X.c+d+)+c.b d 6 ", "T e+f+g+h+i+j+k+l+m+n+X.X.b+o+X.X.X.X.X.X.X.X.X.p+q+r+s+b.t+u+b ", "T e+v+g+w+x+j+k+y+z+n+X.X.b+A+X.X.X.X.X.X.X.X.X.B+C+r+s+b.t+u+b ", "0 b +D+3+4+5+6+7+E+9+X.X.F+G+b+X.X.X.X.X.X.X.X.X.H+I+)+c.b d 6 ", "' ;.L S M ~+..J+]+^+K+L+M+N+<+[+X.X.X.X.X.X.X.X.X.}+|+1+` J h ' ", "! 0 .+s r ++d.@+#+$+O+P+Q+R+-+S+X.X.X.X.X.X.X.X.>+T+U+)+!+t 4 m ", "0 a h d b M.[.N.O.P.V+W+X+Y+U.Z+W.X.X.X.X.X.X.X.W.Y.Z.`. +b 0 8 ", "s.* = 0 b L t [.).`+u.v.w.x.y.z.A. @.@n+E.D.+@@@#@J.K.$@q K , ' ", "8 1 ~ ;.5 f t b.Z c.C d.&.e.f.g.%@&@*@=@l.-@;@o.>@q.r.c.b o o a ", "( 7 ] ! 8 ' U K L >.S [.'.}.!.|.1.2.3.4.5.6.7.8.9.0.M K L 0 = 2 ", "< } ; & 8 h U d ;.G s >.,.'.).&.!.~.{.,@'@)@(._.&.:.<.g m m 2 + ", "[ ; ) = m V f > W n o T X Y Z ` ...!@@.~@$.%.&.*.=.-.e 6 = & 7 ", "$ + 8 y J 4 = ! 0 m * m K u L A M C N O {@Q R S s T n U 5 2 ] - ", "x / 1 y , 6 & 1 2 = 8 4 c o m z A B C D E F q L H d 6 ;.I d 3 8 ", "[ - 6 i ~ i + - ; 1 3 l m i 5 n o p q ]@s t u h ' v 2 2 { w ' & ", "& > 6 - ( . ( ^ 7 & 0 | 3 ! 5 f * b c d e f g h = 2 1 1 i j k . ", "_ : ; < $ [ [ < } ! | ' & 1 2 2 3 , 4 > 5 > 6 | = + 7 - 8 ] ) 9 ", " . + @ # # @ $ % 1 * = + - ; & > ^@' ) ! . ~ { ' ] ^ / - / } "}; fractalnow-0.8.2/examples/gradient_files/gradient06b.gradient000664 001750 001750 00000000573 13175112471 024235 0ustar00mpegmpeg000000 000000 G073 2 0 0x0 0.05 0x270011000800 0.1 0xAF004F002A00 0.15 0xF700AA006200 0.2 0xF900EC00AF00 0.25 0xE400FE00E200 0.3 0xB100ED00F900 0.35 0x6D00B700FA00 0.4 0x2C005200B400 0.45 0x0B0014003000 0.5 0x0 0.55 0x060020000E00 0.6 0x2700A7004A00 0.65 0x6000F600A800 0.7 0xAB00FA00EA00 0.75 0xDF00E600FE00 0.8 0xF900B400EF00 0.85 0xF9006A00B400 0.9 0xBB002F005800 0.95 0x270008001100 1 0x0 fractalnow-0.8.2/examples/gradient_files/gradient06a.gradient000664 001750 001750 00000000417 13175112471 024231 0ustar00mpegmpeg000000 000000 G073 1 0 0x0 0.05 0x271108 0.1 0xAF4F2A 0.15 0xF7AA62 0.2 0xF9ECAF 0.25 0xE4FEE2 0.3 0xB1EDF9 0.35 0x6DB7FA 0.4 0x2C52B4 0.45 0x0B1430 0.5 0x0 0.55 0x06200E 0.6 0x27A74A 0.65 0x60F6A8 0.7 0xABFAEA 0.75 0xDFE6FE 0.8 0xF9B4EF 0.85 0xF96AB4 0.9 0xBB2F58 0.95 0x270811 1 0x0 fractalnow-0.8.2/gui/icons/icon72x72.png000664 001750 001750 00000020152 13175112471 017656 0ustar00mpegmpeg000000 000000 PNG  IHDRHHUGgAMA asRGB cHRMz&u0`:pQ<bKGDC pHYs   vpAgHHyJIDATx͜imgu|<)lfLNh$B$T |(JUm ҪR"Em\QiBT'@B(nx=={s_Hֹ_5яZz-ahmC@a8n"` w]SAiT`e )ztM{wT*p(~z=Czg>֒8|L+~CAk k5dbMT^0UXĐ; Yka2}K`vfFz"8rN&`-2;Ð\yv~`cÆq,E; gywq, á\Zûhdy#Z6&^u"(5$I,eAOݶ C~1NMt -.~'* Z+4{@B3:Cq2cՠZ"x Z2 XRM{dx,5EQ!8kjYVEw\,G_2wVlFt*E:/*D++UdY@ ˞[3 j񰮻AI"%L0ScLǬk.s' ̂9#>/Z ۅb , P4|dLnWRJ j٬RłJE>7;x^Z[j5uJWe ryO9ye:5Ayáp%-/BϲZX4X]ϨT]jBj!(Vp'k}{A R^2%XYmpA3x*Qu áѰ 樝O& ze. J5ZB˚gam2 RJXMNe:5To`? -^^`ae%c84lm96`Oe4f3CeTdqQ*2XV*ʜh00xV4B45 08?º;,ӌn&BT,ƈlmH xe,s$_w]B8e#PLўFC6wǎ#`BtX*W>ChEai4+yP5D(@SwF4V汘rau5ZF#RcL+=ނgɜ 17509sc"(-P0W!y;Y+;b84mIər4l(+U\SNSC&i4h1+ |c|?5Hz_~>Wk];mfJ.24Q$m6[lł@p1 - J\~eAD0 =ө|QFCZϓWWŝ7<#{=\ꏸ">pŴV`)jGS#\UKP )մ)6M&8ZʪY&$Nv@*yp#%0 r+luU2ngdC ;3 ULCY2;Lx }8NxͣrynNTl !U{e^fOc̮]Cf!&ZlZX$ q찶Q}&x~cbc`,9} NɬsgzSo]\YaI̙8BAªyѐ]NkJSa UF$QZh<$x7 < ͽŦbMy{ŀO;e㆗n?$Ÿ A)6z 67)7yJ JeyzIFpe:jZHl։)v.i*k4,'lyx{8T]v_O=BIg:`r9;H G[x_D]v]{Z 3bt/7^?!M}F#\p•"ዕT*z<+6x8,4I#,u]6)Qg6'ı7gL<xTo?k~qȽMLf$6#)Z~пć>7螳TWpgBN:ϻzWZF#eݖZ EOEQdD(i$_z.^{t4EhruD.Mr&݌|gAMw'AbgQ̷Ό)8q&o;>z>x$1s/Rd!&1JOpݚϷosg6=,gy0 k uYYɨՊ_yc,{ݮxfHX Yjd_oW%oS R}ᄏumj"hNA0gu5̨Γnރ&A  d0X`4?X0~t3 GaL897xJ{49j\.g )WL@$lV gLi*A10Lp̄hMnm d ڱfK~}jB'5g6O}>xQ;Oӂ=@t*y5Wa4yEEk 㱓tji4Rllw08]ɩG}ƕW}09} }}/6|k-p*u#oq,FRB Ìg, R^!4So31zk-v8?0;moıXiv?r5Xx녉UNܹؓ *c?xA~Yš4᧞ǏR8 OR7NɢB'oV 1kKHYȲuM0Aq Ƭ@fIrU+.GtWΏ_@ 7Vg- jq >Ň%v=ϝK^xQe6"&xpݮɓZH͜5ͻ~\.j V]?`ĥd.U~ʓ|K^K|WcPc ,onK"W-&ljKQ iaSߜpۍʷΏ,Fn;eKfEGOE-?׬~VF:5X{$)H3aȼ-M5PIB&qӴݻ<3t?7];7W۷ɭ?/6}P# X`VBYA5'VBS# v[2ZM `sӛud[zqOyy!^u{Lìxxݭ .8}•=8.cɬ{ DMy$1?&`&$%`stK1:1.:ѹo_í<ݑr8ZL 1z/N_͗ߎ Hb1Ii[LQ<-d"jUc/ %!,ժe6s*n} w8KcG4oYǩĸߘ`s 3<?`k$axouy]9`Xi]cŞVK*jV yKIKII# 4 k^C̅oqk5$u>CkSnƥ plo7j^72Ff< IgG'x,KȤOSˍ\%}~|?#" Cy ƘC[_#g>׆gGC~Lˮi;wẇɸ(n6oۋ"=ݡMkh_rQp#iŕGq颃C>j5#MSF%MЧRݯ%+__sn,ǞJA;'y e2qjd)yת1ۢ5ɓeT1KҶ" |2ܳhו g^8 =p'd8d:1Wi_}eZ㸼~] 8tg?IIC[-j{.j-O#%0dnqDc&LK,-á3O'RGԫnѩgkK^K#-S:ik3<ñP +xn5a p,Ȓ$/2n1@3 ?7# ),ׄ48:W.hyYr oLV3u:Qp=cwE{pƫ_{w%3 [ZRv߲+!:뚛k!'?:$MbS%yo4"wo S |qtlhNeY.O5H5nWz=wq>NeX^0%pIFQ,7Wz1&|Y8XBlQ9`]d"`,ɻTjN- TzrYH'1Nɓ:<1%%:j$#ɅZv8Q_OHW`Fo,`'`kX4Mx!uꇎ Yck is] =OFd,L8j Ts]*'+OipJ^_t8hwZ|?c{ۙ, V!nc8Cp#S2RVvw@6+.8`ͦs֐e.h56X?wwq6֮2U \Lx,Bϱ:Ҵ"*Oxt],qN+5 Iaz#mt< CvI3]`/sWr{Z-^6/Ulv qh2yӨe84 PͤGK==<̃ P-lcrt+6ap܈c$QO*`rj]/>rY@I1yk+/;e[CÊNv)/s's*Md^3ja(ca`Lz!$Ni߸T"F1H` i͜i,O!&s]ю0N+Z¦U="zM;(JGƅmn:}联/4`GvQ8d4T=)qŋdxFz a,0 }C<U3]5P`֊VmD@^:M RРq:-LZ_RpTRDb^dǡSq0-jC{%]!5H4ךu=2P-kKkH"SPȧӔX*c<*/'a6CȽeQfduVa5eE9N1R^: b2dg9s3meV̂/OliMBc93Ft˙gVp}Tz6/8IBKSyN^9ayɵsrG#(a2@=zfSݮɩAYѝVcDCm>ԫL:>gY$1s80#C*hE\HM!?MLwhٖ )LLPE eJMAk*_2i$Ge{h`9LSiۑqsJaeL&~䳴I4#.KS2#'ZdvPYHeTc;X`՚"):!PCgmB3'Pʔ!we']IzW< h^ڲ)e \4eT+PRS=2(&$EӺBE|>C@歮Z;#ø7[LyJrYVpj6I%tEXtdate:create2012-05-27T10:48:29+02:00+b%tEXtdate:modify2012-05-27T10:48:29+02:00qIENDB`fractalnow-0.8.2/examples/config_files/config17.config000664 001750 001750 00000000321 13175112471 022654 0ustar00mpegmpeg000000 000000 c075 julia -0.743643887037151 0.13182590420533 0 0 0.0116645442238616 0.0116645442238616 10000000 7500 1 0x0 iterationcount smooth identity 0.00035 0 0 0x39a0 0.25 0xffffff 0.5 0xfffe43 0.75 0xbf0800 1 0x39a0 fractalnow-0.8.2/doc/configuration_file_syntax.txt000664 001750 001750 00000012376 13175112471 022402 0ustar00mpegmpeg000000 000000 Configuration files contain all parameters necessary to generate a fractal image (fractal parameters and rendering parameters). Hence it is merely a fractal file body followed by a rendering file body. Configuration file syntax: CONFIGURATION_FILE_FORMAT FRACTAL_TYPE [MAIN_POWER] [CX CY] CENTER_X CENTER_Y SPAN_X SPAN_Y ESCAPE_RADIUS NB_ITER_MAX BYTES_PER_COMPONENT SPACE_COLOR COLORING_METHOD [ITERATION_COUNT | [ADDEND_FUNCTION [STRIPE_DENSITY] INTERPOLATION_METHOD]] COLOR_SCALING COLOR_OFFSET NB_TRANSITIONS Pos1 Color1 ... PosN ColorN Text characters can be upper-case or lower-case. Arguments separators can be tabs, blank spaces, carriage return. CONFIGURATION_FILE_FORMAT should be C075, which is the format described in this document. Other format values (of older versions) may still be supported though. FRACTAL_TYPE can be : - MANDELBROT for classic Mandelbrot (z_n = z_{n-1}^2 + c) - MANDELBROTP for custom Mandelbrot (z_n = z_{n-1}^p + c, with p parameter) - JULIA for classic Julia (z_n = z_{n-1}^2 + c, with c parameter) - JULIAP for custom Julia (z_n = z_{n-1}^p + c, with c, p parameters) - BURNINGSHIP for mandelbrot-type burning ship (z_n = (|real(z_{n-1}) + I*|imag(z_{n-1})|)^p + c, with p parameter) - JULIABURNINGSHIP for julia-type burning ship (z_n = (|real(z_{n-1}) + I*|imag(z_{n-1})|)^p + c, with c, p parameters) - MANDELBAR for mandelbar (z_n = conj(z_{n-1})^p + c, with p parameter) - JULIABAR for juliabar (z_n = conj(z_{n-1})^p + c, with c, p parameters) - RUDY for Rudy (z_n = z_{n-1}^p + c*z + d, with c, p parameters) FOR MANDELBROTP, JULIAP, BURNINGSHIP, JULIABURNINGSHIP, MANDELBAR, JULIABAR and RUDY, p parameter is a complex number that must be specified through REAL_MAIN_POWER and IMAG_MAIN_POWER values. For the others, REAL_MAIN_POWER and IMAG_MAIN_POWER are of no use, so they should *not* be specified. For JULIA, JULIAP, JULIABURNINGSHIP, JULIABAR and RUDY, a parameter c (complex number) MUST be specified, hence the optional parameters CX and CY. For the others, CX and CY are of no use, so they should *not* be specified. CENTER_X, CENTER_Y, SPAN_X and SPAN_Y are floating point numbers specifying the part of fractal space to draw. ESCAPE RADIUS (often called bailout value) is a floating point number used as a condition for breaking the fractal loop. NB_ITER_MAX is an integer specifying the maximum number of iterations used to determine if a point is inside fractal or not. BYTES_PER_COMPONENT specifies the number of bytes per component used for colors. It can be : - 1 for RGB8 (8 bits per component) - 2 for RGB16 (16 bits per component) SPACE_COLOR specifies the color of points inside fractal. COLORING_METHOD can be : - ITERATIONCOUNT : the value returned by the iteration count is directly used - AVERAGECOLORING : average sum(s) is/are computed using the specified addend function. ITERATION_COUNT is only needed for ITERATIONCOUNT coloring method, and should *not* be specified for AVERAGECOLORING coloring method. Symmetrically, ADDEND_FUNCTION and INTERPOLATION_METHOD are only needed for AVERAGECOLORING coloring method, and should *not* be specified for ITERATIONCOUNT coloring method. ITERATION_COUNT can be : - DISCRETE for discrete iteration count (simply the number of iterations). - CONTINUOUS for continuous iteration count - SMOOTH for smooth iteration count ADDEND_FUNCION can be : - TRIANGLEINEQUALITY - CURVATURE - STRIPE STRIPE_DENSITY is a positive integer used only for STRIPE addend function. It should not be specified for other addend functions. INTERPOLATION_METHOD can be : - NONE : only 1 average sum is computed and is directly used - LINEAR : 2 average sums are computed and interpolated linearly using smooth iteration count to produce one value - SPLINE : 4 average sums are computed and interpolated with polynomials using smooth iteration count to produce one value TRANSFER_FUNCTION specifies the transfer function to apply to the (nearly) final value, in order to map it better to the gradient. It can be : - LOG for logarithm (base e) - SQUAREROOT for square root - CUBEROOT for cube root - IDENTITY for identity function (value unchanged) - SQUARE for square - CUBE for cube - EXP for exponential COLOR_SCALING specifies a (floating point) multiplicand to be applied after transfer function, again to fit better to the gradient. COLOR_OFFSET specifies a (floating point) addend to be applied after multiplicand, again, to fit better to the gradient. It must be between 0 and 1. POSi : position of COLORi in gradient (between 0 and 1). First position must be 0, and last position must be 1. Positions must be strictly increasing. COLORi : colors composing gradient. Gradient must be made of at least 2 colors. Colors must be specified as hexadecimal numbers. Red, green, and blue are respectively the 1st, 2nd and 3rd component. Some RGB8 color examples : - 0x0 for black - 0xFF for blue - 0xFF00 for green - 0xFF0000 for red - 0xFFFFFF for white Some RGB16 color examples : - 0x0 for black - 0xFFFF for blue - 0xFFFF0000 for green - 0xFFFF00000000 for red - 0xFFFFFFFFFFFF for white In order for the gradient not to be discontinuous, the first and last color should be the same, for example 0x0 0xFFFFFF 0x0 for a black and white continuous gradient. Acceptable floating numbers are for example : 2.567 4.146E-5 8.26e2 fractalnow-0.8.2/lib/include/error.h000664 001750 001750 00000012665 13175115345 017317 0ustar00mpegmpeg000000 000000 /* * error.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file error.h * \brief Header file containing error macros and stuff. * \author Marc Pegon */ #ifndef __ERROR_H__ #define __ERROR_H__ #include #include #ifdef __cplusplus extern "C" { #endif /** * \enum e_TraceLevel * \brief Trace level type. * * Users should understand the difference between application current * trace level, and messages trace levels.\n * Using FractalNow_message macro, a message is printed if and only * application current trace level is greater (>=) than message trace * level. * * For example : * - Messages with T_NORMAL trace level will be printed if application * current trace level is T_NORMAL or T_VERBOSE. * - Messages with T_VERBOSE trace level will be printed only if * application current trace level is T_VERBOSE. * * Note that error messages' trace level is T_QUIET, i.e. are always * printed, except when application current trace level is * T_QUIET_ERROR. */ /** * \typedef TraceLevel * \brief Convenient typedef for enum TraceLevel. */ typedef enum e_TraceLevel { T_QUIET_ERROR = 0, /*=) than message trace level. */ #define FractalNow_message(output, msg_trace,...) \ if (msg_trace <= FractalNow_traceLevel) { \ FractalNow_debug_prefix(output); \ fprintf(output, __VA_ARGS__); \ } #define FractalNow_errmsg(...) \ FractalNow_message(stderr, T_QUIET, __VA_ARGS__); #define FractalNow_error(...) \ FractalNow_errmsg(__VA_ARGS__);\ exit(EXIT_FAILURE) #define FractalNow_werror(...) \ FractalNow_message(stderr, T_QUIET, __VA_ARGS__);\ res = 1; \ goto end; // Common error messages #define alloc_error_msg(s) "Error occured when allocated memory for %s.\n", s #define existence_error_msg(fileName) "Error: \'%s\' does not exist.\n", fileName #define open_error_msg(fileName) "Error occured when opening file \'%s\'.\n", fileName #define read_error_msg(fileName) "Error occured when reading file \'%s\'.\n", fileName #define write_error_msg(fileName) "Error occured when writing in file \'%s\'.\n", fileName #define close_error_msg(fileName) "Error occured when closing file \'%s\'.\n", fileName #define FractalNow_alloc_errmsg(s) FractalNow_errmsg(alloc_error_msg(s)) #define FractalNow_existence_errmsg(fileName) FractalNow_errmsg(existence_error_msg(fileName)) #define FractalNow_open_errmsg(fileName) FractalNow_errmsg(open_error_msg(fileName)) #define FractalNow_read_errmsg(fileName) FractalNow_errmsg(read_error_msg(fileName)) #define FractalNow_write_errmsg(fileName) FractalNow_errmsg(write_error_msg(fileName)) #define FractalNow_close_errmsg(fileName) FractalNow_errmsg(close_error_msg(fileName)) // Common errors #define FractalNow_alloc_error(s) FractalNow_error(alloc_error_msg(s)) #define FractalNow_existence_error(fileName) FractalNow_error(existence_error_msg(fileName)) #define FractalNow_open_error(fileName) FractalNow_error(open_error_msg(fileName)) #define FractalNow_read_error(fileName) FractalNow_error(read_error_msg(fileName)) #define FractalNow_write_error(fileName) FractalNow_error(write_error_msg(fileName)) #define FractalNow_close_error(fileName) FractalNow_error(close_error_msg(fileName)) // Weak error #define FractalNow_alloc_werror(s) FractalNow_werror(alloc_error_msg(s)) #define FractalNow_existence_werror(fileName) FractalNow_werror(existence_error_msg(fileName)) #define FractalNow_open_werror(fileName) FractalNow_werror(open_error_msg(fileName)) #define FractalNow_read_werror(fileName) FractalNow_werror(read_error_msg(fileName)) #define FractalNow_write_werror(fileName) FractalNow_werror(write_error_msg(fileName)) #define FractalNow_close_werror(fileName) FractalNow_werror(close_error_msg(fileName)) #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/config_files/config06.config000664 001750 001750 00000000256 13175112471 022661 0ustar00mpegmpeg000000 000000 c075 julia -0.4 0.6 0 0 3.15902076051223 3.15902076051223 1000000 1000 1 0x0 iterationcount smooth identity 0.01 0 0 0x39a0 0.25 0xffffff 0.5 0xfffe43 0.75 0xbf0800 1 0x39a0 fractalnow-0.8.2/command-line/src/main.c000664 001750 001750 00000011371 13175115345 020037 0ustar00mpegmpeg000000 000000 /* * main.c -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "anti_aliasing.h" #include "command_line.h" #include "fractalnow.h" #include #include #include #include #include int main(int argc, char *argv[]) { setlocale(LC_NUMERIC, "C"); CommandLineArguments arg; ParseCommandLineArguments(&arg, argc, argv); #ifdef _ENABLE_MP_FLOATS SetMPFloatPrecision(arg.MPFloatPrecision); #endif FractalConfig fractalConfig; if (arg.fractalConfigFileName != NULL) { if (ReadFractalConfigFile(&fractalConfig, arg.fractalConfigFileName)) { FractalNow_error("Failed to read config file.\n"); } } if (arg.fractalFileName != NULL) { Fractal fractal; if (ReadFractalFile(&fractal, arg.fractalFileName)) { FractalNow_error("Failed to read fractal file.\n"); } if (arg.fractalConfigFileName == NULL) { fractalConfig.fractal = CopyFractal(&fractal); } else { ResetFractal(&fractalConfig, fractal); } FreeFractal(fractal); } if (arg.renderingFileName != NULL) { RenderingParameters render; if (ReadRenderingFile(&render, arg.renderingFileName)) { FractalNow_error("Failed to read rendering file.\n"); } if (arg.fractalConfigFileName == NULL) { fractalConfig.render = CopyRenderingParameters(&render); } else { ResetRenderingParameters(&fractalConfig, render); } FreeRenderingParameters(render); } if (arg.gradientFileName != NULL) { Gradient gradient; if (ReadGradientFile(&gradient, arg.gradientFileName)) { FractalNow_error("Failed to read gradient file.\n"); } ResetGradient(&fractalConfig.render, gradient); FreeGradient(gradient); } Fractal fractal = fractalConfig.fractal; RenderingParameters render = fractalConfig.render; uint_fast32_t width = arg.width; uint_fast32_t height = arg.height; if (width == 0) { BiggestFloat dwidth; initBiggestF(dwidth); mul_uiBiggestF(dwidth, fractal.spanX, height); divBiggestF(dwidth, dwidth, fractal.spanY); width = roundl(toDoubleBiggestF(dwidth)); clearBiggestF(dwidth); } else if (height == 0) { BiggestFloat dheight; initBiggestF(dheight); mul_uiBiggestF(dheight, fractal.spanY, width); divBiggestF(dheight, dheight, fractal.spanX); height = roundl(toDoubleBiggestF(dheight)); clearBiggestF(dheight); } Threads *threads = CreateThreads((arg.nbThreads <= 0) ? DEFAULT_NB_THREADS : (uint_fast32_t)arg.nbThreads); Image fractalImg, tmpImg; CreateImage(&fractalImg, width, height, render.bytesPerComponent); switch (arg.antiAliasingMethod) { case AAM_NONE: DrawFractal(&fractalImg, &fractal, &render, arg.quadInterpolationSize, arg.colorDissimilarityThreshold, arg.floatPrecision, NULL, threads); break; case AAM_GAUSSIANBLUR: CreateImage(&tmpImg, width, height, render.bytesPerComponent); DrawFractal(&tmpImg, &fractal, &render, arg.quadInterpolationSize, arg.colorDissimilarityThreshold, arg.floatPrecision, NULL, threads); ApplyGaussianBlur(&fractalImg, &tmpImg, arg.antiAliasingSize, threads); FreeImage(tmpImg); break; case AAM_OVERSAMPLING: CreateImage(&tmpImg, width*arg.antiAliasingSize, height*arg.antiAliasingSize, render.bytesPerComponent); DrawFractal(&tmpImg, &fractal, &render, arg.quadInterpolationSize, arg.colorDissimilarityThreshold, arg.floatPrecision, NULL, threads); DownscaleImage(&fractalImg, &tmpImg, threads); FreeImage(tmpImg); break; case AAM_ADAPTIVE: DrawFractal(&fractalImg, &fractal, &render, arg.quadInterpolationSize, arg.colorDissimilarityThreshold, arg.floatPrecision, NULL, threads); AntiAliaseFractal(&fractalImg, &fractal, &render, arg.antiAliasingSize, arg.adaptiveAAMThreshold, arg.floatPrecision, NULL, threads); break; default: FractalNow_error("Unknown anti-aliasing method.\n"); break; } if (ExportPPM(arg.dstFileName, &fractalImg)) { FractalNow_error("Failed to export image as PPM.\n"); } FreeFractalConfig(fractalConfig); FreeImage(fractalImg); DestroyThreads(threads); FractalNow_message(stdout, T_NORMAL, "All done.\n"); exit(EXIT_SUCCESS); } fractalnow-0.8.2/examples/rendering_files/000775 001750 001750 00000000000 13175112471 020564 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/examples/gradient_files/gradient04b.gradient000664 001750 001750 00000000276 13175112471 024233 0ustar00mpegmpeg000000 000000 G073 2 0 0x0 0.1 0x270011000800 0.2 0xAF004F002A00 0.3 0xF700AA006200 0.4 0xF900EC00AF00 0.5 0xE400FE00E200 0.6 0xB100ED00F900 0.7 0x6D00B700FA00 0.8 0x2C005200B400 0.9 0x0B0014003000 1 0x0 fractalnow-0.8.2/command-line/000775 001750 001750 00000000000 13175146244 016157 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/examples/gradient_files/gradient04a.gradient000664 001750 001750 00000000210 13175112471 024216 0ustar00mpegmpeg000000 000000 G073 1 0 0x0 0.1 0x271108 0.2 0xAF4F2A 0.3 0xF7AA62 0.4 0xF9ECAF 0.5 0xE4FEE2 0.6 0xB1EDF9 0.7 0x6DB7FA 0.8 0x2C52B4 0.9 0x0B1430 1 0x0 fractalnow-0.8.2/gui/src/gradient_box.cpp000664 001750 001750 00000005626 13175112471 020344 0ustar00mpegmpeg000000 000000 /* * gradient_box.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "gradient_box.h" #include "gradient_dialog.h" #include "gradient_label.h" #include #include static QGradientStops getGradientStops(const Gradient &gradient) { uint_fast32_t nbStops = gradient.nbStops; Color c; QGradientStops gradientStops; for (uint_fast32_t i = 0; i < nbStops; ++i) { c = gradient.colorStop[i]; gradientStops << QGradientStop(gradient.positionStop[i], QColor(c.r, c.g, c.b)); } return gradientStops; } void GradientBox::initGradientBox(const QGradientStops &gradientStops) { this->gradientStops = gradientStops; QHBoxLayout *hBoxLayout = new QHBoxLayout; QToolButton *editGradientButton = new QToolButton(); editGradientButton->setText(tr("...")); connect(editGradientButton, SIGNAL(clicked()), this, SLOT(openGradientDialog())); gradientLabel = new GradientLabel(this); gradientLabel->setGradientStops(gradientStops); hBoxLayout->addWidget(gradientLabel); hBoxLayout->addWidget(editGradientButton); hBoxLayout->setSizeConstraint(QLayout::SetNoConstraint); hBoxLayout->setStretch(0, 1); this->setLayout(hBoxLayout); } GradientBox::GradientBox(const QGradientStops &gradientStops, QWidget *parent) : QWidget(parent) { initGradientBox(gradientStops); } GradientBox::GradientBox(const Gradient &gradient, QWidget *parent) : QWidget(parent) { QGradientStops gradientStops = getGradientStops(gradient); initGradientBox(gradientStops); } void GradientBox::setGradientStops(const QGradientStops &gradientStops) { this->gradientStops = gradientStops; gradientLabel->setGradientStops(gradientStops); } void GradientBox::setGradient(const Gradient &gradient) { QGradientStops gradientStops(getGradientStops(gradient)); setGradientStops(gradientStops); } void GradientBox::openGradientDialog() { GradientDialog dialog(gradientStops, this); if (dialog.exec() == QDialog::Accepted) { QGradientStops newGradientStops(dialog.currentGradientStops()); if (newGradientStops != gradientStops) { gradientStops = newGradientStops; gradientLabel->setGradientStops(gradientStops); emit gradientStopsChanged(gradientStops); } } } fractalnow-0.8.2/gui/src/main_window.cpp000664 001750 001750 00000111745 13175131337 020214 0ustar00mpegmpeg000000 000000 /* * main_window.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "main_window.h" #include "main.h" #include "mpfr_spin_box.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void initDefaultFractal(Fractal &fractal) { InitFractal(&fractal, FRAC_MANDELBROT, cbuild_l(2,0), cbuild_l(0.4,0.25), -0.7, 0, 3, 3, 1E3, 1000); } void initDefaultGradient(Gradient &gradient) { uint32_t hex_color[5] = { 0x39A0, 0xFFFFFF, 0xFFFE43, 0xBF0800, 0x39A0 }; Color color[5]; for (uint_fast32_t i = 0; i < 5; ++i) { color[i] = ColorFromUint32(hex_color[i]); } GenerateGradient2(&gradient, 5, color, DEFAULT_GRADIENT_TRANSITIONS); } void initDefaultRenderingParameters(RenderingParameters &render) { Gradient gradient; initDefaultGradient(gradient); /* Init rendering parameters. */ InitRenderingParameters(&render, 1, ColorFromUint32(0x0), IC_SMOOTH, CM_ITERATIONCOUNT, AF_TRIANGLEINEQUALITY, 1, IM_NONE, TF_LOG, 4.5E-1, 0.2, gradient); } inline void initDefaultConfig(FractalConfig &config) { initDefaultFractal(config.fractal); initDefaultRenderingParameters(config.render); } void MainWindow::loadSettings() { QSettings settings; imageDir = settings.value("imageDir", QStandardPaths::writableLocation( QStandardPaths::PicturesLocation)).toString(); configDir = settings.value("configDir", QStandardPaths::writableLocation( QStandardPaths::DocumentsLocation)).toString(); gradientDir = settings.value("gradientDir", QStandardPaths::writableLocation( QStandardPaths::DocumentsLocation)).toString(); adaptExplorerSize = settings.value("adaptExplorerSize", false).toBool(); lastPreferredExplorerWidth = settings.value("preferredExplorerWidth", DEFAULT_EXPLORER_WIDTH).toUInt(); lastPreferredExplorerHeight = settings.value("preferredExplorerHeight", DEFAULT_EXPLORER_HEIGHT).toUInt(); lastWindowWidth = settings.value("windowWidth", width()).toUInt(); lastWindowHeight = settings.value("windowHeight", height()).toUInt(); useCache = settings.value("useCache", true).toBool(); cacheSize = settings.value("cacheSize", (unsigned int)DEFAULT_FRACTAL_CACHE_SIZE).toUInt(); solidGuessing = settings.value("solidGuessing", true).toBool(); fractalnow_mp_precision = settings.value("MPFRPrec", (unsigned int)DEFAULT_MP_PRECISION).toUInt(); } void MainWindow::saveSettings() { QSettings settings; settings.setValue("imageDir", imageDir); settings.setValue("configDir", configDir); settings.setValue("gradientDir", gradientDir); settings.setValue("adaptExplorerSize", adaptExplorerToWindowAction->isChecked()); settings.setValue("preferredExplorerWidth", preferredImageWidthSpinBox->value()); settings.setValue("preferredExplorerHeight", preferredImageHeightSpinBox->value()); settings.setValue("windowWidth", width()); settings.setValue("windowHeight", height()); settings.setValue("useCache", fractalExplorer->getFractalCacheEnabled()); settings.setValue("cacheSize", fractalExplorer->getFractalCacheSize()); settings.setValue("solidGuessing", fractalExplorer->getSolidGuessingEnabled()); settings.setValue("MPFRPrec", MPFloatPrecisionSpinBox->value()); } MainWindow::MainWindow(int argc, char *argv[]) { /* Set icon */ QString iconSizes[12] = {"16x16", "22x22", "24x24", "32x32", "36x36", "48x48", "64x64", "72x72", "96x96", "128x128", "192x192", "256x256"}; QIcon icon; for (int i = 0; i < 12; ++i) { icon.addFile(":icons/icon" + iconSizes[i] + ".png"); } this->setWindowIcon(icon); this->setWindowTitle(QApplication::applicationName()); setAcceptDrops(true); /* Set C numeric locale and codecs for strings. */ setlocale(LC_NUMERIC, "C"); /* Load settings. */ loadSettings(); /* Read arguments on command-line. */ CommandLineArguments args(argc, argv); SetMPFloatPrecision(args.MPFloatPrecision); FractalConfig config; Fractal &fractal = config.fractal; RenderingParameters &render = config.render; /* Deal with arguments on command-line. */ initDefaultConfig(config); if (args.fractalConfigFileName) { /* Read config file. */ FreeFractalConfig(config); if (ReadFractalConfigFile(&config, args.fractalConfigFileName)) { FractalNow_message(stderr, T_QUIET, "Failed to read config file. Falling back to default.\n"); initDefaultConfig(config); } } if (args.fractalFileName) { /* Read fractal file. */ Fractal newFractal; if (ReadFractalFile(&newFractal, args.fractalFileName)) { FractalNow_message(stderr, T_QUIET, "Failed to read fractal file. Falling back to default.\n"); initDefaultFractal(newFractal); } ResetFractal(&config, newFractal); FreeFractal(newFractal); } if (args.renderingFileName) { /* Read rendering file. */ RenderingParameters newRender; if (ReadRenderingFile(&newRender, args.renderingFileName)) { FractalNow_message(stderr, T_QUIET, "Failed to read rendering file. Falling back to default.\n"); initDefaultRenderingParameters(newRender); } ResetRenderingParameters(&config, newRender); FreeRenderingParameters(newRender); } if (args.gradientFileName) { /* Read gradient file. */ Gradient newGradient; if (ReadGradientFile(&newGradient, args.gradientFileName)) { FractalNow_message(stderr, T_QUIET, "Failed to read gradient file. Falling back to default.\n"); initDefaultGradient(newGradient); } ResetGradient(&render, newGradient); FreeGradient(newGradient); } if (config.render.bytesPerComponent == 2) { QMessageBox::critical(this, tr("Gradient color depth is 16 bits."), tr("16-bits gradient will be converted to 8-bits gradient.")); Gradient newGradient = Gradient8(&config.render.gradient); ResetGradient(&config.render, newGradient); FreeGradient(newGradient); } uint_fast32_t explorerWidth = args.width; uint_fast32_t explorerHeight = args.height; if (explorerWidth == 0 && explorerHeight == 0) { /* If both width and height were omitted : set to default. */ explorerWidth = lastPreferredExplorerWidth; explorerHeight = lastPreferredExplorerHeight; } if (explorerWidth == 0) { /* If only width was omitted, compute it to keep ratio. */ mpfr_t spanRatio; mpfr_init(spanRatio); mpfr_div(spanRatio, fractal.spanX, fractal.spanY, MPFR_RNDN); explorerWidth = roundl(mpfr_get_ld(spanRatio, MPFR_RNDN) * explorerHeight); mpfr_clear(spanRatio); } else if (explorerHeight == 0) { /* If only height was omitted, compute it to keep ratio. */ mpfr_t spanRatio; mpfr_init(spanRatio); mpfr_div(spanRatio, fractal.spanX, fractal.spanY, MPFR_RNDN); explorerHeight = roundl(explorerWidth / mpfr_get_ld(spanRatio,MPFR_RNDN)); mpfr_clear(spanRatio); } else { /* If both width and height were specified (or set do default), * adapt spanX and spanY. */ mpfr_t spanX, spanY; mpfr_init(spanX); mpfr_init(spanY); if (explorerHeight / (double)explorerWidth < 1) { mpfr_mul_d(spanX, fractal.spanY, explorerWidth / (double)explorerHeight, MPFR_RNDN); mpfr_set(spanY, fractal.spanY, MPFR_RNDN); } else { mpfr_set(spanX, fractal.spanX, MPFR_RNDN); mpfr_mul_d(spanY, fractal.spanX, explorerHeight / (double)explorerWidth, MPFR_RNDN); } /* Reinit fractal, since we changed spanX or spanY. */ Fractal newFractal; InitFractal2(&newFractal, fractal.fractalFormula, fractal.p, fractal.c, fractal.centerX, fractal.centerY, spanX, spanY, fractal.escapeRadius, fractal.maxIter); ResetFractal(&config, newFractal); FreeFractal(newFractal); mpfr_clear(spanX); mpfr_clear(spanY); } if (args.nbThreads <= 0) { /* Number of threads not specified. */ if (QThread::idealThreadCount() > 0) { fractalExplorerNbThreads = QThread::idealThreadCount(); /* To export image we decide to use more threads that the actual * number of cores, because some parts of image may need much * more calculations than others, so we may have one thread * taking much more time that the others, which is not good * (action finishes when all thread have finished). * In short, with more threads, we "average" the time taken by each * thread. * However, having more threads than number of cores is not good * for real-time, which is why fractal explorer uses exactly ideal * thread count. */ exportImageNbThreads = 4*QThread::idealThreadCount(); } else { fractalExplorerNbThreads = DEFAULT_NB_THREADS; exportImageNbThreads = DEFAULT_NB_THREADS; } } else { fractalExplorerNbThreads = args.nbThreads; exportImageNbThreads = args.nbThreads; } /* Create fractalImage label which will be the central widget. */ fractalExplorer = new FractalExplorer(config, explorerWidth, explorerHeight, args.minAntiAliasingSize, args.maxAntiAliasingSize, args.antiAliasingSizeIteration, args.quadInterpolationSize, args.colorDissimilarityThreshold, args.adaptiveAAMThreshold, fractalExplorerNbThreads); fractalExplorer->resizeFractalCache(cacheSize); fractalExplorer->useFractalCache(useCache); fractalExplorer->setSolidGuessingEnabled(solidGuessing); fractalExplorer->setFocus(); /* Make it the central widget with correct size policies. */ QWidget *centralWidget = new QWidget; QGridLayout *centralLayout = new QGridLayout; centralLayout->addWidget(fractalExplorer, 1, 1); if (adaptExplorerSize) { fractalExplorer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); } else { fractalExplorer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); } centralWidget->setLayout(centralLayout); centralWidget->updateGeometry(); this->setCentralWidget(centralWidget); /* Create fractal config widget. */ fractalConfigWidget = new FractalConfigWidget(fractal); /* Connect the fractal config widget spin boxes to slots. */ connect(fractalExplorer, SIGNAL(fractalChanged(const Fractal &)), fractalConfigWidget, SLOT(updateBoxesValues(const Fractal &))); connect(fractalConfigWidget->fractalFormulaComboBox, SIGNAL(currentIndexChanged(int)), fractalExplorer, SLOT(setFractalFormula(int))); connect(fractalConfigWidget->pParamReSpinBox, SIGNAL(valueChanged(const mpfr_t *)), fractalExplorer, SLOT(setPParamRe(const mpfr_t *))); connect(fractalConfigWidget->pParamImSpinBox, SIGNAL(valueChanged(const mpfr_t *)), fractalExplorer, SLOT(setPParamIm(const mpfr_t *))); connect(fractalConfigWidget->cParamReSpinBox, SIGNAL(valueChanged(const mpfr_t *)), fractalExplorer, SLOT(setCParamRe(const mpfr_t *))); connect(fractalConfigWidget->cParamImSpinBox, SIGNAL(valueChanged(const mpfr_t *)), fractalExplorer, SLOT(setCParamIm(const mpfr_t *))); connect(fractalConfigWidget->centerXSpinBox, SIGNAL(valueChanged(const mpfr_t *)), fractalExplorer, SLOT(setCenterX(const mpfr_t *))); connect(fractalConfigWidget->centerYSpinBox, SIGNAL(valueChanged(const mpfr_t *)), fractalExplorer, SLOT(setCenterY(const mpfr_t *))); connect(fractalConfigWidget->spanXSpinBox, SIGNAL(valueChanged(const mpfr_t *)), fractalExplorer, SLOT(setSpanX(const mpfr_t *))); connect(fractalConfigWidget->bailoutRadiusSpinBox, SIGNAL(valueChanged(double)), fractalExplorer, SLOT(setBailoutRadius(double))); connect(fractalConfigWidget->maxIterationsSpinBox, SIGNAL(valueChanged(int)), fractalExplorer, SLOT(setMaxIterations(int))); /* Create rendering config widget.*/ fractalRenderingWidget = new FractalRenderingWidget(render); /* Connect the fractal rendering widget combo and spin boxes to slots. */ connect(fractalExplorer, SIGNAL(renderingParametersChanged(const RenderingParameters &)), fractalRenderingWidget, SLOT(updateBoxesValues(const RenderingParameters &))); connect(fractalRenderingWidget->addendFunctionComboBox, SIGNAL(currentIndexChanged(int)), fractalExplorer, SLOT(setAddendFunction(int))); connect(fractalRenderingWidget->stripeDensitySpinBox, SIGNAL(valueChanged(int)), fractalExplorer, SLOT(setStripeDensity(int))); connect(fractalRenderingWidget->iterationCountComboBox, SIGNAL(currentIndexChanged(int)), fractalExplorer, SLOT(setIterationCount(int))); connect(fractalRenderingWidget->coloringMethodComboBox, SIGNAL(currentIndexChanged(int)), fractalExplorer, SLOT(setColoringMethod(int))); connect(fractalRenderingWidget->interpolationMethodComboBox, SIGNAL(currentIndexChanged(int)), fractalExplorer, SLOT(setInterpolationMethod(int))); connect(fractalRenderingWidget->transferFunctionComboBox, SIGNAL(currentIndexChanged(int)), fractalExplorer, SLOT(setTransferFunction(int))); connect(fractalRenderingWidget->colorScalingSpinBox, SIGNAL(valueChanged(double)), fractalExplorer, SLOT(setColorScaling(double))); connect(fractalRenderingWidget->colorOffsetSpinBox, SIGNAL(valueChanged(double)), fractalExplorer, SLOT(setColorOffset(double))); connect(fractalRenderingWidget->spaceColorButton, SIGNAL(currentColorChanged(const QColor &)), fractalExplorer, SLOT(setSpaceColor(const QColor &))); connect(fractalRenderingWidget->gradientBox, SIGNAL(gradientStopsChanged( const QGradientStops&)), fractalExplorer, SLOT(setGradient(const QGradientStops&))); /* Free fractal config (copied by fractal explorer). */ FreeFractalConfig(config); /* Create "other" dock widget. */ /* Create content and connect signals to slots first. */ QWidget *otherParametersWidget = new QWidget; QFormLayout *otherParamLayout = new QFormLayout; preferredImageWidthSpinBox = new QSpinBox; preferredImageWidthSpinBox->setRange(2, 2048); preferredImageWidthSpinBox->setButtonSymbols(QAbstractSpinBox::NoButtons); connect(preferredImageWidthSpinBox, SIGNAL(editingFinished()), this, SLOT(onPreferredImageWidthChanged())); preferredImageHeightSpinBox = new QSpinBox; preferredImageHeightSpinBox->setRange(2, 2048); preferredImageHeightSpinBox->setButtonSymbols(QAbstractSpinBox::NoButtons); connect(preferredImageHeightSpinBox, SIGNAL(editingFinished()), this, SLOT(onPreferredImageHeightChanged())); solidGuessingCheckBox = new QCheckBox; connect(solidGuessingCheckBox, SIGNAL(toggled(bool)), fractalExplorer, SLOT(setSolidGuessingEnabled(bool))); useCacheCheckBox = new QCheckBox; connect(useCacheCheckBox, SIGNAL(toggled(bool)), fractalExplorer, SLOT(useFractalCache(bool))); cacheSizeSpinBox = new QSpinBox; cacheSizeSpinBox->setRange(0, 10000000); cacheSizeSpinBox->setButtonSymbols(QAbstractSpinBox::NoButtons); cacheSizeSpinBox->setEnabled(fractalExplorer->getFractalCacheEnabled()); connect(cacheSizeSpinBox, SIGNAL(editingFinished()), this, SLOT(onCacheSizeChanged())); connect(useCacheCheckBox, SIGNAL(toggled(bool)), cacheSizeSpinBox, SLOT(setEnabled(bool))); floatTypeComboBox = new QComboBox; for (uint_fast32_t i = 0; i < nbFloatPrecisions; ++i) { floatTypeComboBox->addItem(floatPrecisionDescStr[i]); } connect(floatTypeComboBox, SIGNAL(currentIndexChanged(int)), fractalExplorer, SLOT(setFloatPrecision(int))); QHBoxLayout *hBoxLayout = new QHBoxLayout; MPFloatPrecisionSpinBox = new QSpinBox; MPFloatPrecisionSpinBox->setRange(MPFR_PREC_MIN, std::min(std::numeric_limits::max(),(long long int)MPFR_PREC_MAX)); MPFloatPrecisionSpinBox->setButtonSymbols(QAbstractSpinBox::NoButtons); MPFloatPrecisionSpinBox->setReadOnly(true); QToolButton *editMPFloatPrecisionButton = new QToolButton(); editMPFloatPrecisionButton->setText(tr("...")); connect(editMPFloatPrecisionButton, SIGNAL(clicked()), this, SLOT(editMPFloatPrecision())); hBoxLayout->addWidget(MPFloatPrecisionSpinBox); hBoxLayout->addWidget(editMPFloatPrecisionButton); hBoxLayout->setStretch(1, 0); editMPFloatPrecisionWidget = new QWidget(); editMPFloatPrecisionWidget->setLayout(hBoxLayout); #ifdef _ENABLE_MP_FLOATS editMPFloatPrecisionWidget->setEnabled(args.floatPrecision == FP_MP); #else editMPFloatPrecisionWidget->setEnabled(false); #endif connect(floatTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onFloatTypeChanged(int))); connect(fractalExplorer, SIGNAL(fractalCacheSizeChanged(int)), cacheSizeSpinBox, SLOT(setValue(int))); /* Set widgets values... */ preferredImageWidthSpinBox->setValue((int)lastPreferredExplorerWidth); preferredImageHeightSpinBox->setValue((int)lastPreferredExplorerHeight); solidGuessingCheckBox->setChecked(fractalExplorer->getSolidGuessingEnabled()); useCacheCheckBox->setChecked(fractalExplorer->getFractalCacheEnabled()); cacheSizeSpinBox->setValue(fractalExplorer->getFractalCacheSize()); floatTypeComboBox->setCurrentIndex((int)args.floatPrecision); MPFloatPrecisionSpinBox->setValue((int)GetMPFloatPrecision()); /* Add widgets to layout. */ otherParamLayout->addRow(tr("Preferred image width:"), preferredImageWidthSpinBox); otherParamLayout->addRow(tr("Preferred image height:"), preferredImageHeightSpinBox); otherParamLayout->addRow(tr("Solid guessing:"), solidGuessingCheckBox); otherParamLayout->addRow(tr("Use cache:"), useCacheCheckBox); otherParamLayout->addRow(tr("Cache size:"), cacheSizeSpinBox); otherParamLayout->addRow(tr("Float type:"), floatTypeComboBox); otherParamLayout->addRow(tr("MP Float precision:"), editMPFloatPrecisionWidget); /* Set layout. */ otherParametersWidget->setLayout(otherParamLayout); /* Create dock widgets. */ fractalDock = new QDockWidget(tr("Fractal"), this); renderDock = new QDockWidget(tr("Rendering"), this); otherDock = new QDockWidget(tr("Other"), this); /* Set dock widget properties. */ fractalDock->setWidget(fractalConfigWidget); fractalDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); renderDock->setWidget(fractalRenderingWidget); renderDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); otherDock->setWidget(otherParametersWidget); otherDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); /* Add dock widgets. */ this->addDockWidget(Qt::RightDockWidgetArea, fractalDock); this->addDockWidget(Qt::RightDockWidgetArea, renderDock); this->addDockWidget(Qt::RightDockWidgetArea, otherDock); setTabPosition(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea, QTabWidget::North); tabifyDockWidget(fractalDock, renderDock); tabifyDockWidget(renderDock, otherDock); /* Set current tabified dock to fractaldock. */ QList tabList = findChildren(); if (!tabList.isEmpty()) { QTabBar *tabBar = tabList.at(0); tabBar->setCurrentIndex(0); } QMenuBar *mainMenuBar = new QMenuBar(0); setMenuBar(mainMenuBar); QMenu *fileMenu = menuBar()->addMenu(tr("&File")); QAction *openConfigAction = new QAction(tr("&Open config"), this); openConfigAction->setToolTip(tr("Open configuration file")); openConfigAction->setShortcut(QKeySequence::Open); connect(openConfigAction, SIGNAL(triggered()), this, SLOT(openConfigFile())); fileMenu->addAction(openConfigAction); addAction(openConfigAction); QAction *saveConfigAction = new QAction(tr("&Save config"), this); saveConfigAction->setToolTip(tr("Save configuration file")); QList saveConfigShortcuts; saveConfigShortcuts << QKeySequence::Save << QKeySequence::SaveAs; saveConfigAction->setShortcuts(saveConfigShortcuts); connect(saveConfigAction, SIGNAL(triggered()), this, SLOT(saveConfigFile())); fileMenu->addAction(saveConfigAction); addAction(saveConfigAction); fileMenu->addSeparator(); QAction *openGradientAction = new QAction(tr("Open &gradient"), this); openGradientAction->setToolTip(tr("Open gradient file")); connect(openGradientAction, SIGNAL(triggered()), this, SLOT(openGradientFile())); fileMenu->addAction(openGradientAction); addAction(openGradientAction); QAction *saveGradientAction = new QAction(tr("Save gradient"), this); saveGradientAction->setToolTip(tr("Save gradient file")); connect(saveGradientAction, SIGNAL(triggered()), this, SLOT(saveGradientFile())); fileMenu->addAction(saveGradientAction); addAction(saveGradientAction); fileMenu->addSeparator(); QAction *exportImageAction = new QAction(tr("E&xport image"), this); exportImageAction->setToolTip(tr("Export fractal as image")); exportImageAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_DriveFDIcon)); exportImageAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_X)); connect(exportImageAction, SIGNAL(triggered()), this, SLOT(exportImage())); fileMenu->addAction(exportImageAction); addAction(exportImageAction); fileMenu->addSeparator(); QAction *quitAction = new QAction(tr("&Quit"), this); quitAction->setShortcut(QKeySequence::Quit); connect(quitAction, SIGNAL(triggered()), this, SLOT(close())); fileMenu->addSeparator(); fileMenu->addAction(quitAction); addAction(quitAction); QMenu *editMenu = menuBar()->addMenu(tr("&Edit")); editMenu->addAction(fractalExplorer->restoreInitialStateAction); editMenu->addSeparator(); editMenu->addAction(fractalExplorer->stopDrawingAction); addAction(fractalExplorer->stopDrawingAction); editMenu->addAction(fractalExplorer->refreshAction); addAction(fractalExplorer->refreshAction); editMenu->addSeparator(); editMenu->addAction(fractalExplorer->zoomInAction); addAction(fractalExplorer->zoomInAction); editMenu->addAction(fractalExplorer->zoomOutAction); addAction(fractalExplorer->zoomOutAction); editMenu->addSeparator(); editMenu->addAction(fractalExplorer->moveLeftAction); addAction(fractalExplorer->moveLeftAction); editMenu->addAction(fractalExplorer->moveRightAction); addAction(fractalExplorer->moveRightAction); editMenu->addAction(fractalExplorer->moveUpAction); addAction(fractalExplorer->moveUpAction); editMenu->addAction(fractalExplorer->moveDownAction); addAction(fractalExplorer->moveDownAction); editMenu->addSeparator(); QAction *editGradientAction = new QAction(tr("Edit &gradient"), this); editGradientAction->setIconText(tr("Gradient")); editGradientAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_G)); connect(editGradientAction, SIGNAL(triggered()), fractalRenderingWidget, SLOT(editGradient())); editMenu->addAction(editGradientAction); addAction(editGradientAction); toolBar = addToolBar(tr("Tool bar")); toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); QMenu *viewMenu = menuBar()->addMenu(tr("&View")); viewMenu->addAction(fractalDock->toggleViewAction()); addAction(fractalDock->toggleViewAction()); viewMenu->addAction(renderDock->toggleViewAction()); addAction(renderDock->toggleViewAction()); viewMenu->addAction(toolBar->toggleViewAction()); addAction(toolBar->toggleViewAction()); viewMenu->addSeparator(); adaptExplorerToWindowAction = new QAction(tr("Adapt to &window"), this); adaptExplorerToWindowAction->setToolTip(tr("Adapt fractal explorer size to window")); adaptExplorerToWindowAction->setCheckable(true); adaptExplorerToWindowAction->setChecked(false); adaptExplorerToWindowAction->setShortcut(Qt::Key_F); connect(adaptExplorerToWindowAction, SIGNAL(toggled(bool)), this, SLOT(adaptExplorerToWindow(bool))); viewMenu->addAction(adaptExplorerToWindowAction); addAction(adaptExplorerToWindowAction); switchFullScreenAction = new QAction(tr("&Full Screen mode"), this); switchFullScreenAction->setToolTip(tr("Switch to Full Screen mode")); switchFullScreenAction->setCheckable(true); QList switchFullScreenShortcuts; switchFullScreenShortcuts << QKeySequence(Qt::Key_F11) << QKeySequence(Qt::ALT + Qt::Key_Return); switchFullScreenAction->setShortcuts(switchFullScreenShortcuts); connect(switchFullScreenAction, SIGNAL(toggled(bool)), this, SLOT(switchFullScreenMode(bool))); viewMenu->addAction(switchFullScreenAction); addAction(switchFullScreenAction); QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); QAction *aboutQtAction = new QAction(tr("About &Qt"), this); connect(aboutQtAction, SIGNAL(triggered()), this, SLOT(aboutQt())); helpMenu->addAction(aboutQtAction); addAction(aboutQtAction); QAction *aboutQFractalNowAction = new QAction(tr("&About QFractalNow"), this); connect(aboutQFractalNowAction, SIGNAL(triggered()), this, SLOT(aboutQFractalNow())); helpMenu->addAction(aboutQFractalNowAction); addAction(aboutQFractalNowAction); QAction *escapeFullScreenAction = new QAction(this); escapeFullScreenAction->setShortcut(QKeySequence(Qt::Key_Escape)); addAction(escapeFullScreenAction); connect(escapeFullScreenAction, SIGNAL(triggered()), this, SLOT(escapeFullScreen())); toolBar->addAction(openConfigAction); toolBar->addAction(saveConfigAction); toolBar->addSeparator(); toolBar->addAction(exportImageAction); toolBar->addSeparator(); toolBar->addAction(editGradientAction); toolBar->addSeparator(); toolBar->addAction(fractalExplorer->restoreInitialStateAction); toolBar->addSeparator(); toolBar->addAction(fractalExplorer->stopDrawingAction); toolBar->addAction(fractalExplorer->refreshAction); toolBar->addSeparator(); toolBar->addAction(adaptExplorerToWindowAction); if (adaptExplorerSize) { resize(lastWindowWidth, lastWindowHeight); adaptExplorerToWindowAction->trigger(); } exportFractalImageDialog = new ExportFractalImageDialog(fractalExplorer->getFractalConfig(), exportImageNbThreads, imageDir, this); /* Eventually launch fractal drawing. */ fractalExplorer->refresh(); QTimer::singleShot(5, this, SLOT(delayedInit())); } void MainWindow::delayedInit() { if (adaptExplorerSize) { fractalExplorer->restoreInitialState(); } } MainWindow::~MainWindow() { saveSettings(); mpfr_free_cache(); } void MainWindow::aboutQt() { QApplication::aboutQt(); } void MainWindow::aboutQFractalNow() { QString applicationName(QApplication::applicationName()); QString applicationVersion(QApplication::applicationVersion()); QString homepage = "" "fractalnow.sourceforge.net"; QString title(tr("About %1 %2").arg(applicationName).arg(applicationVersion)); QString message; message += QString(" %1 v%2

").arg(applicationName) .arg(applicationVersion); message += tr("%1 is a program to explore fractal sets easily and generate \ fractal images efficiently.").arg(applicationName) + "

"; message += tr("Copyright (c) 2011-2012 Marc Pegon ") + "

"; message += tr("Visit %1 for more information.").arg(homepage) + "

"; message += tr("This program is licensed under the Lesser GNU General Public \ License."); QMessageBox::about(this, title, message); } void MainWindow::adaptExplorerToWindow(bool checked) { if (checked) { fractalExplorer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); fractalExplorer->updateGeometry(); } else { centralWidget()->updateGeometry(); fractalExplorer->resize(preferredImageWidthSpinBox->value(), preferredImageHeightSpinBox->value()); fractalExplorer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); fractalExplorer->updateGeometry(); } centralWidget()->updateGeometry(); } void MainWindow::loadConfigFile(QString fileName) { FractalConfig newConfig; /* Set locale each time, because apparently some Qt * methods change locale. * For example a single call to QPixmap(QString filename) * changes back locale... */ setlocale(LC_NUMERIC, "C"); if (ReadFractalConfigFile(&newConfig, fileName.toStdString().c_str())) { QMessageBox::critical(this, tr("Failed to read config file"), tr("Error occured while reading config file.")); } else { int finished = fractalExplorer->stopDrawing(); UNUSED(finished); fractalExplorer->setFractalConfig(newConfig); /* Config is copied by fractal explorer. */ FreeFractalConfig(newConfig); } } void MainWindow::loadFractalFile(QString fileName) { Fractal newFractal; setlocale(LC_NUMERIC, "C"); if (ReadFractalFile(&newFractal, fileName.toStdString().c_str())) { QMessageBox::critical(this, tr("Failed to read fractal file"), tr("Error occured while reading fractal file.")); } else { int finished = fractalExplorer->stopDrawing(); UNUSED(finished); fractalExplorer->setFractal(newFractal); /* Fractal is copied by fractal explorer. */ FreeFractal(newFractal); } } void MainWindow::loadRenderingFile(QString fileName) { RenderingParameters newRender; setlocale(LC_NUMERIC, "C"); if (ReadRenderingFile(&newRender, fileName.toStdString().c_str())) { QMessageBox::critical(this, tr("Failed to read rendering file"), tr("Error occured while reading rendering file.")); } else { int finished = fractalExplorer->stopDrawing(); UNUSED(finished); fractalExplorer->setRenderingParameters(newRender); /* Rendering parameters are copied by fractal explorer. */ FreeRenderingParameters(newRender); } } void MainWindow::loadGradientFile(QString fileName) { Gradient newGradient; setlocale(LC_NUMERIC, "C"); if (ReadGradientFile(&newGradient, fileName.toStdString().c_str())) { QMessageBox::critical(this, tr("Failed to read rendering file"), tr("Error occured while reading rendering file.")); } else { int finished = fractalExplorer->stopDrawing(); UNUSED(finished); fractalExplorer->setGradient(newGradient); /* Gradient is copied by fractal explorer. */ FreeGradient(newGradient); } } void MainWindow::exportImage() { fractalExplorer->pauseDrawing(); exportFractalImageDialog->resetFractalConfig(fractalExplorer->getFractalConfig()); exportFractalImageDialog->setFloatPrecision((FloatPrecision) floatTypeComboBox->currentIndex()); if (exportFractalImageDialog->exec()) { imageDir = QFileInfo(exportFractalImageDialog->exportedFile()).absolutePath(); } fractalExplorer->resumeDrawing(); } void MainWindow::openConfigFile() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open Config File"), configDir, tr("Configuration (*.config)")); if (!fileName.isEmpty()) { configDir = QFileInfo(fileName).absolutePath(); loadConfigFile(fileName); } } void MainWindow::saveConfigFile() { QString fileName = QFileDialog::getSaveFileName(this, tr("Save Config File"), configDir + "/config.config", tr("Configuration (*.config)")); if (!fileName.isEmpty()) { configDir = QFileInfo(fileName).absolutePath(); const Fractal &expFractal = fractalExplorer->getFractalConfig().fractal; //mpfr_t spanY; //mpfr_init(spanY); //mpfr_set(spanY, expFractal.spanX, MPFR_RNDN); Fractal fractal; InitFractal2(&fractal, expFractal.fractalFormula, expFractal.p, expFractal.c, expFractal.centerX, expFractal.centerY, expFractal.spanX, expFractal.spanY, expFractal.escapeRadius, expFractal.maxIter); RenderingParameters render = CopyRenderingParameters( &fractalExplorer->getFractalConfig().render); FractalConfig fractalConfig; InitFractalConfig(&fractalConfig, fractal, render); if (WriteFractalConfigFile(&fractalConfig, fileName.toStdString().c_str())) { QMessageBox::critical(this, tr("Failed to write configuration file"), tr("Error occured while writing configuration file.")); } //mpfr_clear(spanY); FreeFractalConfig(fractalConfig); } } void MainWindow::openGradientFile() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open Gradient File"), gradientDir, tr("Gradient (*.gradient)")); if (!fileName.isEmpty()) { gradientDir = QFileInfo(fileName).absolutePath(); loadGradientFile(fileName); } } void MainWindow::saveGradientFile() { QString fileName = QFileDialog::getSaveFileName(this, tr("Save Gradient File"), gradientDir + "/gradient.gradient", tr("Gradient (*.gradient)")); if (!fileName.isEmpty()) { gradientDir = QFileInfo(fileName).absolutePath(); if (WriteGradientFile(&fractalExplorer->getRender().gradient, fileName.toStdString().c_str())) { QMessageBox::critical(this, tr("Failed to write gradient file"), tr("Error occured while writing gradient file.")); } } } void MainWindow::onPreferredImageWidthChanged() { if (!adaptExplorerToWindowAction->isChecked() && preferredImageWidthSpinBox->value() != fractalExplorer->width()) { fractalExplorer->resize(preferredImageWidthSpinBox->value(), preferredImageHeightSpinBox->value()); centralWidget()->updateGeometry(); if (sizeHint().width() > width()) { adjustSize(); } } } void MainWindow::onPreferredImageHeightChanged() { if (!adaptExplorerToWindowAction->isChecked() && preferredImageHeightSpinBox->value() != fractalExplorer->height()) { fractalExplorer->resize(preferredImageWidthSpinBox->value(), preferredImageHeightSpinBox->value()); centralWidget()->updateGeometry(); if (sizeHint().height() > height()) { adjustSize(); } } } void MainWindow::onCacheSizeChanged() { fractalExplorer->resizeFractalCache(cacheSizeSpinBox->value()); } void MainWindow::onFloatTypeChanged(int index) { #ifdef __ENABLE_MP_FLOATS if ((FloatPrecision)index == FP_MP) { editMPFloatPrecisionWidget->setEnabled(true); } else { editMPFloatPrecisionWidget->setEnabled(false); } #else UNUSED(index); #endif } void MainWindow::editMPFloatPrecision() { bool ok; int new_mp_precision = QInputDialog::getInt(this, tr("Change value"), tr("MP Float Precision"), MPFloatPrecisionSpinBox->value(), MPFR_PREC_MIN, std::min(std::numeric_limits::max(),(long long int)MPFR_PREC_MAX), 1, &ok); if (ok) { MPFloatPrecisionSpinBox->setValue(new_mp_precision); if (GetMPFloatPrecision() != new_mp_precision) { QMessageBox::information(this, tr("Restart application"), tr("You must restart application to apply changes.")); } } } enum MainWindow::FileType MainWindow::getFileType(QString fileName) { enum MainWindow::FileType res = MainWindow::UNKNOWN_FILE; std::string sFileName = fileName.toStdString(); if (isSupportedFractalConfigFile(sFileName.c_str())) { res = MainWindow::CONFIG_FILE; } else if (isSupportedFractalFile(sFileName.c_str())) { res = MainWindow::FRACTAL_FILE; } else if (isSupportedRenderingFile(sFileName.c_str())) { res = MainWindow::RENDER_FILE; } else if (isSupportedGradientFile(sFileName.c_str())) { res = MainWindow::GRADIENT_FILE; } return res; } void MainWindow::openFile(QString fileName) { enum MainWindow::FileType fileType = getFileType(fileName); switch (fileType) { case MainWindow::CONFIG_FILE: loadConfigFile(fileName); break; case MainWindow::FRACTAL_FILE: loadFractalFile(fileName); break; case MainWindow::RENDER_FILE: loadRenderingFile(fileName); break; case MainWindow::GRADIENT_FILE: loadGradientFile(fileName); break; default: /* This should never happen. */ QMessageBox::critical(this, tr("Unexpected error"), tr("Unknown file type.")); break; } } void MainWindow::dragEnterEvent(QDragEnterEvent *event) { const QMimeData *mimeData = event->mimeData(); if (mimeData->hasUrls()) { QList urls(event->mimeData()->urls()); QString fileName(urls.at(0).toLocalFile()); if (urls.size() == 1 && !fileName.isEmpty()) { if (getFileType(fileName) != MainWindow::UNKNOWN_FILE) { event->acceptProposedAction(); } } } } void MainWindow::dropEvent(QDropEvent *event) { if (event->mimeData()->hasUrls()) { QList urls(event->mimeData()->urls()); QString path(urls.at(0).toLocalFile()); openFile(path); } } void MainWindow::switchFullScreenMode(bool checked) { static const QMargins margins = centralWidget()->layout()->contentsMargins(); static bool fractalDockHidden = false; static bool renderDockHidden = false; static bool otherDockHidden = false; static bool toolBarHidden = false; if (checked) { fractalDockHidden = fractalDock->isHidden(); renderDockHidden = renderDock->isHidden(); otherDockHidden = otherDock->isHidden(); toolBarHidden = toolBar->isHidden(); fractalDock->hide(); renderDock->hide(); otherDock->hide(); toolBar->hide(); menuBar()->hide(); if (!adaptExplorerToWindowAction->isChecked()) { adaptExplorerToWindow(true); } centralWidget()->layout()->setContentsMargins(0, 0, 0, 0); adaptExplorerToWindowAction->setDisabled(true); fractalDock->toggleViewAction()->setDisabled(true); renderDock->toggleViewAction()->setDisabled(true); otherDock->toggleViewAction()->setDisabled(true); toolBar->toggleViewAction()->setDisabled(true); showFullScreen(); } else { if (!fractalDockHidden) { fractalDock->show(); } if (!renderDockHidden) { renderDock->show(); } if (!otherDockHidden) { otherDock->show(); } if (!toolBarHidden) { toolBar->show(); } menuBar()->show(); if (!adaptExplorerToWindowAction->isChecked()) { adaptExplorerToWindow(false); } centralWidget()->layout()->setContentsMargins(margins); adaptExplorerToWindowAction->setEnabled(true); fractalDock->toggleViewAction()->setEnabled(true); renderDock->toggleViewAction()->setEnabled(true); otherDock->toggleViewAction()->setEnabled(true); toolBar->toggleViewAction()->setEnabled(true); showNormal(); } } void MainWindow::escapeFullScreen() { if (isFullScreen()) { switchFullScreenAction->trigger(); } } fractalnow-0.8.2/examples/rendering_files/render02c.render000664 001750 001750 00000000134 13175112471 023547 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING TRIANGLEINEQUALITY LINEAR CUBE 1 0 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/examples/rendering_files/render04a.render000664 001750 001750 00000000116 13175112471 023547 0ustar00mpegmpeg000000 000000 R075 1 0x0 ITERATIONCOUNT SMOOTH LOG 2.5E-1 0.5 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/examples/rendering_files/render01b.render000664 001750 001750 00000000133 13175112471 023544 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING TRIANGLEINEQUALITY NONE LOG 6.3 0 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/command-line/src/000775 001750 001750 00000000000 13175115345 016744 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/examples/gradient_files/gradient02b.gradient000664 001750 001750 00000000134 13175112471 024222 0ustar00mpegmpeg000000 000000 G073 2 0 0x3900A000 0.25 0xFFFFFFFFFFFF 0.5 0xFFFFFE004300 0.75 0xBF0008000000 1 0x3900A000 fractalnow-0.8.2/gui/icons/icon256x256.png000664 001750 001750 00000202735 13175112471 020037 0ustar00mpegmpeg000000 000000 PNG  IHDR\rfsRGBbKGDC pHYs  tIME0T" IDATxԽydU;we[꽪޻uF,B21A0`f1CLLxǃcL<8l!I1 VwUյ?=߽y̛Jؓ*_̻|Y~w~~|_! 0$D38@{lk*ө2Z-DGGp&BNg}]Dӯg1ߦOuV 8:G0$,?^ycѿs̞ea nsVC L!zS|睽^9sV678S.0|s߶&\s޹-xO`8!+7iښBD9~qW8{BI>}#I_\yOtFwE˜O1Yh(4}q<6Q~~b0(˾_svmquYd `{%m>z}ѱyOkK6Rhxů?N k䳯Y6A0ZFR(0עȂLF46i7G{j5z}B qv#B!iQD3ǭwPҌgL?Ӟ0?6*(KG"pt8ůG#wNqv=?!.DH;\9ʳ5f H4!`tyd| h a5̻Pwr㯺mec#gI'2ѓ]ic{Q4 NŰ52M>߲N1;;oXBͯzS`1xb$(/cЖS ˪PjM?B'ҽu !Po+ehg0Tp]%\tB;vptD?'Oѹ-!g#(8l)]wB- Vr\^&$){MPl,{&,5{LJ߷j R@+Ec$FSeR,^{ ᶬY5(>$Nq?y_,x_+_'Tt9S JLN Vuo:M~|;i2h>)E8pDߩeW*H7k0yl< aT]ed=({X>af:`osH,'U >dmbl5 Kr$շl/#t ɍTTna'#\f @_l;a~sIΜ$e4 ,)EKAۍ!eyp>(/΋tPR%ccZvfJFRmhIsiN6 *Пg9g49Zd, Kyoq:%16RQ?ly[㱀Q@{8?z6$3M^'' ~.bۭxNl|?%se<& K'8jLrQ:ݸ(U`2 |\7+ܸA0 mZ;ϒ"lM;ՀD ˪9mkk4 = .CW!eKJN~'uQd(2l `:U h)VJ6P:igw{ut]~2#U+ k8[SX[HA@"<*Q!8TP,9[TSM (eZzj>""0iUö PZ.*@ZXqT4dB`+؂g2Qa:[DŽr@t4i5N J)KOcw}Aϣ=+~OF_ ϞM0NGS:Si2Y G7R+΅"5"+{N[]DZ TVG$l-wkL02{4g`:M58: T)#p;2@!5hVMOf)HGQDG4fR^~@\$j{R2]Pxx$X*$#[+T*y=8M20uQs(UzQP3{qnm›W=~Y-IYBkHEy O" )=(M8f}OJR#vR d/i*yt,`ZwNt)9\?J$HP7{ C^t|!ςI\RPZSYF$݁ nI6ǜ PheDZƲQ%lOĴ E=J#"5C36{oŸ T収@!ppsa`M8Ѯ d2!pW(wWm.!wzTEHCN|,4749ac68yQԨSt,, N!]+,pZFdm-+@flO~}ZgVd'\3֗UQ`*<@k ,Y05/0M^`"n ΍G#J],Զͭn"^@++)󙧉VrKJ!M 607|2Y}]$]]Fc-<Wӑ28&L[ӛ .{3gf3ᡡ x2,2n~ss~i&Qu| +z 5T!}ԞǑjz7#jUl R1(kOR\C.mveYyiO^v{;Ge 4{c2WZ LL6ɉT5Η/!E ~0T::>D:Seܩb͊T5)XNi.O9Ng g6ZXKrNNe2|G7 R K"W>ތbtxQ0PN0P3qO"E!߈VD\Ӽ ypiQS,,K3NF#a+DZtɛ_?G8 +h!E޼I?p!gCbTuUsyhDēM-#$*nKp}.\u7f!1X2XG88H5.μzГ a4R:5SCM66}i)-]$k!^v]6"n*&լcYn$Xͤ=P]C)+h5V"+!w J-j\D$bs:MNE~a0{ڡ(;B:ϕYLLDH oE<韷mz/͈:!U%gKk%=MIA^(ˏ`(Uy>} YuɵuVTBJ@X_L&Ǒ0 $).lʖ vwقs'a nP6^ܩۉoj5 -0J\FL|HZ_ &J|/2>@`K ikYl|$ʙUχid99UTom{5)h|xE .e<)Nh#LK_hؓ j%զk&Ĕ,}M&\,! -BHWDPv)I~J)sNV LvesSʤ )z9-qI/nM-S퍍)67vw+nH*y9 c)M@M y{0]hʨR-R*N?= t!{=ɄN۲L3=Fךf( 4$hF bm ڂg\lh E t@(tfd`4RV89a"lTwW1NO1tYirC,LC+F&D^>̌A%*:I~)EVQ\ʶ{s>V>{QBmt>o F} ut}taD"yVHCJ?GG ʘPTJr2Ey(' Wq*E!d_e8&cXzYЪFJdBm:uLjT-M,J{iJ(qFL,Rzԗ\a!Z=jJHϛJkxbZE7Q1XX:H߼tKky|RI ٺpQ]WD:*i D94=g(ol$EӲ}:2f1@_X҃LuH״}_i;gl4<>8eR5.,3-{ CqPIgp8 eK{y=''˅&Ee5O3r4tucuA2㷶^$]Vt DHd*K1Y 3z~ ᇑ~K3րQDH +YZQqbr;Ϣ#`'MfǙ+=UƘU*!,^8TZ| ߉1` Cf %,&*f1b+aIr~vye& 1م& 1rhdҳUREV66x8W.eRW5L4BQH34`R&;Л ښؘRn mQZ:Ҟ4ѽIOA^n~ESӷl4?#[es'Em,.KdGVJYʰo h!$D5쎏iF19ZZYBE_0񱍃٠ڶxl.!MyCMU*dT5j5Պs:өƆBa:u'R+08Nlm"Lp|L3f#@`BNoHAdĪk!bDA"QW)qLttDFe8Nb<D; vBbcC6"=<#$!it: &A7ɈftjhU"] d?.[VXXF"U1T@RSq% Pg揅u򎎒4dA^/!ţL˷PUe0ectz4g86 KIǞJh(xlH46ZSU҇nCf7(u,+Ykk;0۹=hV9uvDK;fyC6)_pNi91a  GzZeie҆RJ7ZE_dYDs0xCN۝ {դ!':fJ7pǤE;;千hqVԑURU`f>d[Bgh[f1F=5_1d4Y9c|?d0g/;,-36c.G`LLL CfF #E<4܆K,Xemn{XpsKzyӁ"#0r 9P\Qj)(x Y`ܹW P1VIIN[0@d`s3Bk T*7ąm+Mu]2G1A㱩qܒ XD&Pa$@Ύkל\1UcldMI`cV-JɉMI}w.b-^$r|׮mu#{U*ISrf+|osD$YPוy٫$ԖA%$.* p2!4cKs)v7Qp> Vk!(eB)&fc+ Wz^msk%Saz-miB2$8>80d)rrbB IDATF&e`!.{x)c*~M_FBd!*X[ f\Tr4B:|Z=VR27oҿʸeT#'N;-=Y uV430EPitx:8s&@ci*+QB_][SVCD Py0"]qg@0G߷uHζpZǙ.&vVAd@a0۰gjfs(² `5!n~=k,+0`CtpaoT#W@dVPT"v5vʄ"!( qHX=L;YYKJi="8IǧP+/ W5~o-c0l:JH+aRuIf!^lI 0[[I{?/=x9h*p37<Jh pETƱ3XĨZA4"FUض̠>  cJv"wqd'' M/@ܸt0Bϛ&@k0fo| 7tWT#0Rc: ?jU nלJ{~l|[{{ƌ0IefnQ((%RbMPI;2(M<f&Y{{0 &8diO5j@JxuF; #pg҆LWEZ$ULa!DE$N4[{6''Jirع<}YI"onF0 .ǤMGe քLhLoxc.@gxݵ*7a #`lFu$M'j<-Ȉ''$B)G4)):_h<#x≢"LY<>wĆ9}''V,Up >*.]3''ţmr/Ο²\Ԛreh$@)' +z7\cZD"y= _F\%e8ҟ0q7peUԀו7('NQy*YuNAxDmn}ө;N54FZ, < _&\'kLs5g Aԅalb4ruϻJo5 40kYFKiV`{l&w_RJI)/v/t6B-p'idct ˜uH ܶ7o=t{{qsWU &j#8#l~'9|CP%:i>H:cRWzUݵkcއǒyQBЏE0UizSd+:A aL@`:4]ٜ`:b+odO4 AJ4,Czھ5Lǒ~c&;03|& M{:yL؈3wJQOx8| Q |?Íxc O^"HgoO^? p-Z>hhT Pq|b"R%r(  ML&ne^Fv$H~s?K> gY3ס7q2B<~o(.E.n , JX |AN \^簎kYmyvv̼6 i vU&4ӴťBҽ"7:p"L2f\ Àz0MLsF`G'@d½CP>>Ce\?>qw~@enp 0mғ߄swwau*(@@ #eCA`h-Jek@)C ȴ*-Kiш0Pp/pPF{?<<ʗO_c ` PY @4FOF`~e`Iҳdab84tD6O HI䄱<*q︚h`G2$]R<>h}Z|ݴe BX!Ȧ"nl@{{ .e EeJ{W 8<4HE\AԧS5U*#>Q\7^eE5T*8NEĉl u JMLWQ|N@5@M&@xoB}N_: }}! #Xo*ݨ?m#P|t `^N ]#V e7ũ? B ~Y ( y`*\ʴeiIeooUo {2E@BmgB45ɂ sfs5 o^g, Wm|, vɄd^lF}vUbp{nn:ib{ s1> AP`7(/A\`88bGF+4?I n rr/(5&0 ;.I# 1zNM݆F҈-#T2,m:NxlөׁprbcS A)˒U<*2bPP 9ms)Ť++o%{H 2{e Śfӂ<. Hr_]"mӗXG_iQ 5Ab! 1Xxa܈AF|PbNk6|쵎0Lk}9Ͽl﹌Q B5>!`4+qσ ĸJ(b͵Fө T$,i\ijC|izipp`#bh,\,OX:l"΢t`(2O'SX77YNL(%ybHAkc@=m~Qؓ`Qh^ވs{#np +.UO*|0Bhn]/|=uEhw8cx[.5?fņƋ ;HlDx07`۬d4\ PUxBߖLj4")qDtǦeg΄8:2*Z krpY޿d狈 e@ 2ՈXOi0ѐ!ye"c 1.p7nTfyzs؀@YbxV"]+|^ȾȌ[ vch0kĆ<"(?,Ѝ#&&G^υR 4J˒Kj8M-)~@H>JyoQ 8&z l~*AE]Liס92[i_D&̎M!d-N&5##yTqg&!w֋404Y(%/ `hHLJ}-&YTƱ>?@ԍ8LƝ =D޳{Ov|-ēF B(Ё8~_7~MTk^7VOk{_{+m~ӴQ~Cm || 4Xa|)Cjq 8w@ |hnPʊ?c6)c67}]&Ee^^LIL@z{x`Xlo0?}zh ;co@Ƣu vDvw D=(q0\2D=.ha/oao1\vy({v?yk-K<{88tx#ϣh dX\ -&9 NIW@Ga.LGOZM ~ߌ:bx0*Cs~'RIӛiɄS M[/Th48eګtȼB:D `K1b,>ny7n- Gmm)M)BӆIb8LCR*>4XlIsHv0Zkm̓Rv@8_OwzGHF߃{~kPvѢxƈ_2z>©n p D (`?QBWvsg[o/é0r>P^G{@ԂpzƵ= 7\f(r̘58hs) 89C=} \PX -<:0%Y%\,U1 ,iKM;d1g8 wpYT 4(㡳! ,uMq؞ Tl17WL-8234D|rN P$b۔RuH#GZ/gʤ4Y$J1yDzH{q94 Af{PW]4/T_'TVg=<`Lc0yEf|qel*#^zs;Io|qW#%}FlAg)|u nڃ{X1|KnOuOrpnf\wt ".cg1yӉq+_@*ṡ^* S`шg"V<Ge\Yt2oJQBҊTIItk+&92m2,XH< J2w4*L.g*gKeMS!GGZ & D XԞ)=S&\kt9c8LuOjՍS9Q WE5u:x'w 8ν.3=T[ 3/p :3 U0R7poOo]DEɻ-O>v{;ًM6.p<N5;'ёiGp邋_^ć}O?x[_й_ p:ϯn Z#_j^g_z?=+xSg!^\D|7^ ‹CL#DѫKo(K#&B {>~h5xg|?՗Fػ~.|w|5;0r!&PG-Sȏ_9vcშ~+dd4U&Gp:9l7w"7UMG"[&Q FNt_G{O2meizzF2kqcyΖS4I#D5$*2&|2q;R2R4S1܌1VFF#RD4 5ѮӸMwv{^y?'Qߺ=t~Q776ᅧPG}":B|𨉗{/"އ~3#tpi2z&G5]J)ϟ Cvqi|ammv_?i¿Pe\޻Ǯ⑻Fu[2Lv\\ПarE{u WG T 7_C4 rba<6Rܤo*VS0" O#IqmuVCP! CCr~lrvn& ӻ,xq[tEy00A1q|Lsz,͑D:w!=*CV%tQőKp!11ذ,ҵj5D3DMyqM\K߂οo/o?C o~Ϟ=G#~"!EJ ݛbp\C{1wSo#x_]S;0>'\x7W&ꄣ Dqoa9|;{7O)Dc_ |MPw-k6Yq5)q} y)K^@,,izhΟ7ntx|^@SS֪Tid:oe(wM|D_&֔Iq#3b8,):ؓ<]”|03,o )< 5G&4&3m#R[p]3fQBn3v31hV7+qK*>_à;Wp6~my+߂8>+Bo_3^{ELHcҀ_GG|by4.~K"9r?>``<&]AJͤg= xp#."{;T&p]/:Ԅsv2j%0k `/'{x]`š9]:81G_OV|WqO;?\zmx&>ƏP } 7+ <x$i`:57$2g'j5T,MEI r!t:(B\R%=HO &ĒZLt8"*ˤDH auRJ-˾f(JPrj5s=h DzKt)F6`BZM1Zǜt,@1t}Ӝ4M).ً~f򏙪KS ^% 4cc=7(^}a o׭b_hʭgwxvzϏo3/9ܳz˫{9Dy kmRx1!fRaJ]fXi*1qEMX, eK = ]"]JX_gL[-1 w.a2V*WO:lד1\zDF#4J7”i4)((}H pzx^ٳVL2&1 tTcQiDcywCշޯi5p}7nq0~ .:0 N'C%ܿIHa&`cͣ,>ӝo$$Z#a0x 1vlxx[b;$ӳՏN(|m77'w"4:A6Ňt+_j8h]l {BT ׂ+Vk &׼+ ?dqɐ2QB$K9'ۅf3M(d:^C:/GFC|cPVU6CYYx裘Zhݧq:`3y&PЮ~'+cd:bzgz1EQDU4#$$-h j\WT&~IbdjShL6CXZW,.t,,[9R-XpYh!O8FJV_s5̈́iu`уwV TS}EV~%%ROLh6Idc\8vU "=-nFhRJ<)!uA`'i-"d*\GE37l=$ ?ev́F@MZٴ9nڭY8M_8yY^ñ^{8a0hN@]皈TUqq8QL cA2 B!4kܪe\! iu;:*(rh4LnIa"~KeԆVrW؀vh2eeOܙ=EؘJNrEa)7$m8,0:* a³0(M$5ia6l. L!l=5'2xkq&J@p]S6 cuְ@ðZ6R[`ׁ΄T7h6|^q+~gO5t& Fo j CR`t:^1!`_`@/DQ(l6UdnǮVM&Š/. |rl8sM/vz59h5^O0 w9~<4|+‚pHt\#);*dg$TH 5$FAlz[O(vZT˘h8ä,g`$ `M}tCr#?B/xg;/<'ZtoWG#cPt)#;T^M~*y8]yq=c&*>/+|>6I!YZRinov-gõNvǩH+x::&فř3*[#Kk~_'V",^Xur9?:ıflLղU@:[ ܱ=oR*I[#Jeց]8Iga 7 F% =>]q=I)ooԬy2''vsݒ_&π?6=syp*:/<ƧWtGyG_q{\nu wv#o>I~獠v_nKJ CeeJErZkmzq4~0(,mS͋|^j-W^Y \",g/)>_FUD'(,bjz:v][ԔN4YgZ@ZDIv͗t]{ Z1fllHK|^y1á)qM.ȯ,)zAR-+eЖ2Cbbgp('?) _n噥)޸1Cq"6y&;<[2}ijoۖPQ*@.EP%9F%(UmJ] J%DAWl5b*(}>r IDATj0`YiCg^^^0>>$8<-:epoL5Zn QjznL(qdoQhQUQGAE[GrK뀲=,:=/~p;zVAۡQzzgpfύ{}䴩TSqtA`Xga_+YK+z &=wߥ +7b$l:.ZZD>{+R+,ŦMbEeUZ12Pj }\+G(Q'= h 5bS ?0ho:eZ%D@ݸbJΎAf5/Kd6o=yݼ|~?Z/w#~6xhƑ,n޳Hnd_捤X=x{lDB"ƪC%T1(_;:&TT ^\ZY+LU j;hUF+ JfkFJfzX,.,u[MCȈfj*^[Mu{P޳ ^Ni7^S~M(Ւ=]㮣f_oQg Sʗ:3`hI,&i <0iZ ʈ, NqKlӥآvl̩ 7kE(z-) DGAz{eOzfn]m{z0ʡHw[֯evu6iVb)nJ% j})g)nm0) J 4PV:NR*(< (g)ʱ;z:O_Nkf&C /k%:ƍ",jP4s](B| yFsY6}y7s ϮJYnr3G4'T8^/?O&kpP@ōDԳTҔJ:}*Y@ZLB/kؖj b~_1@ IJlHq|[$kđ[]tJeY8o Yk**ƺAx&A8~@-M45_lz}lU )m|ͿkM7#*WFQ07Wv7X`ʫ!3C緦,x/-b~jt#DQh· ΕnkX$K.Pb)&~8 ˶R){HK3 Iΰ Sd+Pb[rVH_`}DVqtb°r Hp+ ^zA\nHhNVdq.qk^GL"0ad{XfFTEi>>OPyl0¤Y dM13CE43@xpy?Mj6o Zv\(xh0b"4\״ z4sM"zPv|^ pCuOi1!t~ETQOr>cOQ9kex# LyZ22ȿ7 Y}p=dYQ0ԫ2]ה0^֘#s#ŢNtW!SFsy`z25e<0~zVp#YZ!(FG>?u%{וqϏX*TV8>knXGG9pL;/:NCͼ7x ?yP"\<[IvvnNwk~XkvUa-SqtO3jY7+oP]'=a)TnSr7zQl_ u񯼞򞙏 ,q/Qbp7!1ΧsZ>B~]7܀#4 /ÿWUg9}eZSx~5d7Kt?9t3l~ia^EɠP&9tOpk^__oW) ;LUVAt%r1hiE[[w6I@%ZX-V*Ob3fc~|7`?³'Zj͵Šv"^g&A"51')Y՞qN'nw2"P%=|}\NI&Wc̪m > c8xfNWO?Ɓiz䝼):{_~o}Np6ZmUM ـCņ !{+< HG^[6P,U㜜0~VH t:Isa=mex]Tzy'*w? c̈G y0S|q\#S!7=~sH۷|?t~ƣ7\=30y %D0iQc|s^+xNzlxa;Os,~lB.BZp(I !salou~ٸj6%1z1Vн˴cyVu+Kev d*92uEc ;?X6tJR}ղI (?=^ı*}?"\WD:ͨ!̚M@l5#SrǦ^"j̡_ m^GZ9pe4O+_:~gfNrn8n#GhxaOG}(a+pTQi^O˅o~qj8T5B#s. >wPnAMT`5:-g8pgfj-s FQs KE~n~c bP ^Xvp8K/3 yv~[Ϗ3&nh8 e=eS"Su^$2Q,*pu{}JN,Tw?{ ԓ"VSI!؁To9x'( V9]N4Գղ|_]}N ?ꤶ,qU.Z.KE &L(M.۷AY ϲ]ZcvՔJ*Tj9>ne dh)m@ Q*0BbWEuEs @瀾&?"]mުS ?=RW֤XW:b&oL5>pΜ8oq|=^fu#p-14y 6YP rKzV6VW.4>JN/ӵCj4,}1 ii_R`QXPu>0\7OF-~wD`C+`F{J k&?j>oCf 7@{?x#"0ѧJ?gPQÂэhz^)=b",'|}/iy^d;s[ΐ.QYίZU!ޛLˏ4޸QS(Zv*ۍBOM.-PHvxbJ%>T6I,u.JnL;єxG_(@4&C6}T:3^W'K:;3zvGNL_+z)Ubs;!ݷ&qPEXt\hLKN+L)qz!z{BK0.’v`0HVS@gv'*#Ohr ĦYkbr9ˡT^pzm&S?ZTf\~ݬKj{Jn|-E>E>z,Nsf!. 4_ˠ.0zz* 'uc0`pʯJM6\ORTe`_h-† ڔR Q,׬:Xl0C )E`)|?J}qD AƀR5u9T.BJagsqy=z Ã'|t9l,w|JquJ ހ?؛Qn< +a^[ɗuߺ\w-yd HXSy; Ě ﬓ%^&e;?=W)'ڻU]Q3۴XsQ7AGp)iɏ/wuG|qFr?^qoO}z^w}5xmF4cFm]*K!:u*t,Rjs8f*H˥ۄj#ּmi,OVKj5/ZM*qm[B?2= P?Rd=8jI8C7tL=?b IDATSקk2ߏAUW$3D?y/5-YZ>3hPno͡/'v?Lj7>Mׅ:.?|g~86#R?EqrݡΚ>+TJ2YY|" ~[ق@@wS'<[yXg,"egHKCM5PP(88N;dθڜ5㺻$(U*tvpvw Efq&2H:')/ocZB]y|TF^Z_v3qlF-偮y/SuZ|LF/SZM%HV{j[e_mVBO՜l6Y# }dD2M(J 'Zh QBcsjH:/[2~՟1}݊D&iӏm>*Qqύ<8mw.v.bJu~k8R"_>%ߤHO}f~WG߲40fZPLXĨR'H.7ڬJTt:i6U AI4Ţb8ma'N$/XrA_2矑aʫ)J:ިt^wI_+~&7M|__@w4<6ϟƝGf>ߦwѭ|g4r8%ӠkjOۇn; ^Eg7rO>+j~=;_q'fJa%bFfc8Cڝ2Dk1"s)[8NِHLsJVKQ(jٮ)cz=~_[1;;:ƗC[bQ15`.Җ.)1|1kn~߮)=IJ١ql$5h3!z\\_|k^\(WR 41N9!^e׷~$TVTcv58ZKPq\@-H} :n[m 26*bt"@Z׍.h$+ 0a-w2-@'D3e Nv @MPAysD' :&xMU]Fz8 .O|p="EJO~6~WLn`1SLJhGk0`0P5Fkqa-@~m P,VR!"Z-v[pҰp_O&ʈHTGd0Jtl&6E{ 9\7 Kh]DF̩?.RnpvĄapK 7U$Jm2lUT((Ӈ߈܈irEn[i_ik|\Wm߶ӧ֣!Oܧ\U#(U4隆=)s:~PR+iSOYBASPis] Trq9j}p ?#TK0 @@ j(1Zflqp+!|,jy C'2͚x+ IP#¾R.vs?`e5-NނR[Lqi>*(zK}N2gx|9{=Bk<{f_1+W**3L>ʶ?P\{#l~M7g}`("Q$-@<`%-7%*e4^ Az]g pe7jD,0KR{%}8YO߸|Bؑ̀XIbCE4Rv;gG>gy'PjX/tž1JU0L3ÕeCqLRTP^\.z`^`ȝqlo ޸aNt}+nσz_$|ScPYd͛Qr̙F~^%"NX%T8[^)hTWb\NcxnzCb-~vm!_V@D(j5 5ҝgv>qI)Yg@c~N\or2CJuѺ84ŒI'*>ܔ#4Exl(X^eth>]#{!\~lt_Qoح['N7_Wk-٭e1fMẒ́"'O>oVPz*%'ZSζݮ W׍&ʓjCAVqt'^EYBL!_3ЄCz)o@D>GJf,/[P $%Cp @ A̡Gl3i+_b:q2cKg|ňon=D}d=ruOokPaC1B&nWai*KQ烁Tv{`k%HUC_VRX9EYR.tlK;0ɖK?muu`X;k >|8.E%V#f`93+P@x0~oȦmaAB}}ش ssS"J7L ZǼۯM:Fy^w3γ1{/M}X Ma"sƪfUF.pyͶЅaxseK) ̻MXMx;Xd_DR(% Qz*dXyoFC%CQ ^>Xi%l\Et$Dk^3EDK!%qltI+fz䋌vTp Mfu8r(gEIKbǙy;܁Yq~.䔂o? 9e=$O||#'qmu&C"^`Tٖ$d`8ـX|>r6Z?Z.Gj8}cc$2^ =fX%whŐzݣMáALU5e8,fȂc7ߡf^f!5(v#$m3C8L8WWq6?Ƴ=Sa~8f-rCNwWExx5ۛl JE2<:x^RITL|+D\*Z7!zĉ])fA^_jX+B0pUL;ӛ Ub*j+`[r. PL?5'VAPaz/'IcvSh|g{ fNP6OQ6CT #fn$i>}=TGٹF^8wͿs'^0u^a=\JKWR;`dET # q\q %إkFyV5€s9eB.o0x)6 Z&fq6I6킵 eft4d~K4EsP'I[4##1KKUKeKC+_2d@q[s&薬LGvM.$BThC+HI(!_P\v5 'wsIǹ#|.Z*fr{qP"2ۆN_Hկv?$ejj,ZMׄ{g.ͬD^p|@[q=hM\dP *kYzMp59O$/+q]} |N}8/* ."u2esZ  ]7qv rQJr:8;4 qzz^d0s dDg։i?6fZrE<1BL:YImV[-Za0ժNɖssV^d-Ӑ% FՆ>j)ekO~y1ar}M:mc"7z70[ \ď>Bԫ㠜9<*ıKzyf)^'UW٘ɪg~eRXK x1'LMJlZ+ӬT ].&v% d$RR)Tj9"UH.M أgDh=ֲDГA lkևkE|'gz3mG*Ws\ϱ0r- x=7K}51Ia8SuPN KGF7oL(B1O~|ùPsv;kׄģYZR˾n֒(2fx,~ Z7WVI+=vZ+jvFJ 0bz:dqMtrV\T(x`h4T1!eUP*pn5%AFɪuEM(5&!VŸmn"J>^cx@N#4Kd6~ *{9<8n~~l̙_f69C/_ϱ]vS$42fb3GM8[:W\Ot~nJ;vRf(áCղiVJXLՁ,ݯiTjϧ{2bllc/&NC+ j l2k;ɮ6+hЧߟHD@-iWl8[e"o6*oE_~+3gOeV>U˞|}$&~ySml?Mg_ "=e\GnB<ӊ=sg/j4鋦*Q{0:?7w/AWO]/B{ojY88N)h6D=ӱN-,f >uTd)aq1kxvNWkYqȞւדD0>I._gZM%4;#{S)=!R*쪵E Qf`|ZB?i"4} qUMA~NoP>"Nw%~o/;J Da֩*wg)=߷:ymnݿYgPPUYS߶(M_FMtVl/NQ_]!Muu\D.W C|ͼ'>P(ҙi] d D}nlˊL ME x)p| =] 4 t:VL/k/V2y'6flG۵NF)9#8!aX&]L2ef9i=kyGg ?,\͵xuvJ=vn?61G'gI} 51/׫x9#l~7ร7xrZ(UwF2YCQo"p z.q\m~r_mkR*K@Cv0 pX,S(ZyϦ>\W(BAS(  @+r1Q+eƖO+u\ZR-MXPXW?{o%uw^DdDY{ H!R2I˖deImyH3c Ycx[Ƕ|dY%%q3 "$b_kɪ3"qߋ̪̊jf$yNj̈޽OIn< A8( h=Bc§YM-v:F]Ծ%n jv> q.HˠB<:G4*_ֳ_gu™w_a/->!h3NHv"k~ @2erJ'ѿo(w ~Ġk},Y/6}U7?IY?`9d%qݩ߶aVV gy[vfהhat2nRQB/Z<\W%!JZ<?PLRZsFT*^|jB D$[,REA?k`7Ty(UG[Zd֖q݈'| IVjdtmPRwGtFX#Pq2mUTz=ij Gwu I$Pf-=#pb3Tk&> Ht|>> |#W^{:7߬+ϱ䷮ROĔuSꋃk61%{mE(Qs:5;a.ms(@|֖$i-m &zXttQH1v]zJBOVR躘/0i++p]a/./𼈵r.,Z-6c)6}Rɕ>M)s\z|R܊q P@Q?q < (4Eqo1-*yTG!QPgEMИKP60.[~n>x(q8J7W!"5Oo§.?m8'Ϡsh`PL^jt$x IDAT'ğD8֠X@VK`MCn vHe;E]+[tObV+U9 xdvŽ^RφJ%C8 *Y|R$m d3JȃcakswN4QT⮀:{F*W"#܉YNS}q|T=6}lFUSWP }Uzhz`+_(ҨjFkqn v Cxox[y:8}VZ< އ?J //<@-j.tweڽUL=)Ce#v]e .Д6]!:d|#Pc$@ZKGkiYcj~`Uy`:P{܇/S.đHI$PZbQf F=)GoM 7%TQz&04'vh]1Y2أx(VLo`a,=؜Gki 4h{/ @c`b/ο,oz3ĥ>A}s >7;MaNwE9*wm3o/oF#4+aq1=Iץw6!䑑leAlsiy!lHP*i uGr*F/!M?y7v,j%|]\=hP"MU4E~~Wi=e*3uQ܃oz(4JCivZ0V:ͻ~YI~^& J%)6 AE;[ITzIC:Yp]Y|%R}@ɾ˄j44J)՘v5jT aňa8,RnmT6 d^c,⎉@pH.q\qhJ%aV4 jQbWh xH`6 []iUQR[t}Y/+vv~sONG W_M9z:>hy I}7>jUM^u4%\U L']A:áq{yw#[!!U c-@\v)-~TJH1f_{C K{Qt8YY2~)oV5ͦK,&P.Ki-uhxވ^oϫC8q"FH b1(ȑmGfP()кH9ıPJB)֎ oځESFBkx=PW:$ o8_x;(}y^<;|24~L <?Grߍ14][Π( #0x,TmáV'Jٗ{2\yx\rj{B Nn Mrrivwm%KNlRnWC>T(h8O޼JEH狀IX‚,j4{Gp̚ 4*;Ǖ*BJȡw2 fI"Gq0tP3TZN 0:(uKG|_q*-6yrXe*y^?>r-}/?0U<.̤DQ؀ 1JET*2t:+6Yˆ?gbGp}(KVA#RI%%:H ڳd)KfEbK^q{[@ }y*lbq*2 z >EtNS(IMRcI@S,oxkwf埥RhOQJ1:I!32)31^?N +Ps%)U(.S'PTM>STbw&ǚ+>@spϛD8 (T hƹjM-&TZN~bzOu_zߕiXy):RFru:jv ;C6,.0 K 7C43iid:8N ړw;;Ǒ𝝬8vZK;),Hn3ٸZMDUYJbOY,f+yOEluXF/ӌ&OnݰozYZduu~?%4 sKiPщF8&w!fׯ}QJژ qzcc0(0:K @YAߐBon x%]t<`3𱫿NkqBowg<[7| $Q81Jl?Eqhl =(i3=yM扉&n^ ^9?6"L'czi+*fl{cA:&Y64R1ٱ(k 8)4#g9 s&!)ɍ"J~rg1aXN8!`1)ƜdgW"/' _˽aSx.\rvVgkr3𩧾_~]|eT1o=@fA:I`=]+h6 A իBՠVk uIYwk,356-V~ ;/&OTJSe9'oŢXP>o|ay桓Jr TTŘ\Vv{ܯPkh6*es Z)8 3C^W, 璞ӂ"İ"# %0@}({G7zqa9nr_}ohwvxOiq}]MŏllN#GN\ΎnqUe|MU9"ʒQlh*xOJz?՟vT?Ӫhpѥ%W67lv@HEoUqJ۶_&A'} jLJCodVq1D;ؘqkZ L UJs꿞%`4 ]gl?*PpƐk PX– c4$znRI.lNLՆ1)6 +pzgcJ O.X_:ݝC (] K]/>/O~./.̦T*cY𼅞;,!1J%czx8%E^/X Z.6P"D@}:qL&(ÂjcU3qq,mR! 5iԞ$eފE%jWt4z$s3m;g]~_yɬEx2)UYoZV~'4qh+bΎi9בHxz Йe]^HN`[v,4(q>3Ϡ6W#31tfKx|nlݮ y7+pa#~:˯q7',g.Eq{ǟeXbsܹ{>q|78 D8 Aas7c _(rۻ践X J[ S&DVE qPV&F'D:KɛM!K<8 [}._5e)tBF3t/}a  *<̡Zլ◰ CV[`1Q{.(ÔBA'-E MfAvL'c}wŇ]\?bu~TQ>v14yʼ+^9͋g|><Gfܧu|Mp \jy ;x/<t?W^6Rwq~A?*s7UP5G T7V7.OUe ^!|qUPέb^8^f0ڷ^6Ž0eZyL"ϫ'+᥌%Y6 hR J%T%!= ݩ[ii>d ltQ& ɿ_Ly&ia}`}YObmRM('%ͅ}Mz(:I heRZ=ةTbm/ldxALtıcJPP8F+0L d=^p쎫XzVn*<_?Ǒpyp1IL+6E^{)}S/9O9.Ǹr\-֪s}G?os|w~ }&gX(!mOu7X/wo ke>wkW?}+;7zǨ}+%#-peRbx4#߳#+ǁ휤 T"{uZ+C %~~9z7O t2rd+*RdZ[3ـ΂o}ryZ͊DRG|mK(3 _$DŽ+= {[tL! :E/V~jVT{ﵣ^OD?QxXv%=D }u4 _~Khss=ί7Oyk΁cU` KA}K_g5ܷ?}uc#Jטy iůmor:~뷞`ȟ{ [,ß7>5N^Or_p7>/lׯptea(np^Z"Q1,#J=b#rP^; s;њ\PDQ~ߣ\GEم'EXzϽ7yN?V~:.cHJL}&8ד"(%nm{A}c&E,ʈ(rƞ4rS}q=46͎zlSnWQ,*k5/jnסݞs)vY[ IDAT"b ,=D/?V;Mn.^):p?ݼ/S*=#,x[,LbdT3(,QaLSD5.Urմ;.ǩ^JEDG ŐZ 67=Gjؙe$V+u;{ZN!)(" 4i^dR|gMa ?%HcgPjj5E(&W:xĪfN^6N(-48i66 }nDU* v\hbLpQ Q4oy| $m1V/<2w?E7ʶ ,M6 c8+u *,!8Ht5ƾlVcbkyӈOhCٓ?o ~ |`de7>o;,I\'y#7bV4&aTD"׫P,qY&XD#Bb]9DcNxܦ9]#P#A9E(vЌh,)ŋIxm~ǞD,#.HKҪhebڴIYRjN3MhMϛ3.}G h|PQ,h$h6K` ەnYZX[sFgu+o̪ ڇY- @SS5l~Ύ1-YYti{s|_z]sEa X~rGyM!pR1AOS Ь{Q^JHS}RJ^8vM'p |?|aꫤnx cNJX4'{Ke0mŸ͙v!"_X/KLy}U_o-_Wvglj)a>)i%FEt}sz^7ݮv@빉Amleu_C6{+)ayt;k V2 KU `?,m6{4|4[Hdh$<.dK{!=&W bwWڗ`Ii7qokܚ$9u4rO~l G\:A0qR]ERAmh5s'5oc\pymͭ+׼,/oO{G ).㼚=sm41,{20n(K&Tia \0tcm*q<ֳܥbe%bsS60WV̪ON%`?r9gM#cժip+O虀K^0К0rO_d ETSl%=G]s{E75(+ꦟ/!&bM-.Z]&Ѩuھ_E$".ו S-Bf[ XV>¥K.QGjaϻb:o`WVYDX(wnNsJ ;=bTs3|֞NXarR=]P.P-;Iz69V(9RҐ9AJLB C1eihT1d" mB<қr3K7-"69T7Rzs"p9M`T)B\*MKZ + Bһ+R.q]7+5VP%ce7en)UqKl5 Ub!61BجsD<o-~}i*?w\߇WU&Da\gXRɓ  *a9N(!UgZpZ{d_K"Jaw,XٌPj@_7T2Z2,*4uHFpst 8~ >| gٷOS1^ mLQıkڔiT(rS/kn.kj0o[˺j#clf(Jk.F& N;lUH=]*4&)SE_.FyKfm*,aݶYsVH岈76p]'~G# S(h}⸂R5Gul(m` Z4w_a`C'>vݣE<q%snJ:Vp|itG3|B;Ȝ5=$o4rLF_06`ξW)t:֙GHfq(c*8Ju)ujl>&U&^o٘wv$ºtmnB^nY{*Nod#7mvA.S6 TכMWQH-f hoϟ rX@j ^O-,W*/A#W5ElnVl$Q|_'~MO`*)`JE`*$JhV.fqybQKLz¶czO|ctK/P-XXԟy3^'_gƥ|a B|7XUN]!y|7Vf4dFzL}"qNt qdUzlY~_0[ uZ4hnz qj$ EhTKƈ֒.o[`Uycs=-Eug{::N]5s?Ilb2 C}:1wrRӤ N-׉y\*RLq4N|54s.8!~E{< uF,s>(Sc_m#|3(uJInC i i*`ZR.:7itiR) b,{M>{mdۃudU8yRƦA6f{b rhXa83 uC#Sj 'Q(񃆬]4[?+|x*oׯ?yen3 cMGFF8q"F#ppaf-G#P}'Yv Ez)%y#G"]Zk7B΢Nٟd\%ׄ j-8luߴYz\Jo :=~',b{fMMG#,_ Fv7JORIi)Gbؐ1[s4aOqhޫ+Q~c8tf8Bk88FL۔5CT*ru)/q:=*|{ X6[m܊aQU66H~IA+q qFn|/bF#g̃nW6;eL*ل׃r}vѧFH[$٪ğVvg7;O]PzwWhX[.D4*?S.bl6Ss`PNT܋EUR4blj7:ZƇ4bb7> f5*Sex^D{d9Dk&=椮T1R_\ywP%EC^-l߁; 5P2ec& %3ّ PiqvG'~Y$.vۡGC ZLF<豠Ѓ,&l$ғ%5%fXEٛ|sS# iFrӉ{G1R)~ss!(D13 1'Jh]uc[YurbF߀"'?*z(?D|q`NPuzH$h0 H713̦+i׵a1gGҗzvv<66T&G'|NJ4Oжdަ] ~[2:[>/ĝӧ;{ZUMq "؜\k>NzTҿ/-ŴZNlή6RGc j3ST(}+vs[Дˑq*2٬-Z@PwДJGGFЦ?*;LL`NF 900`ںݢatikXe]f]dTԓVT;;^B+}LSz@u:Hoi(qޔNVv].Ñ#6*LNNPڹ9X_RJ߀ կkz7>!ilѩEch~ 9G&M,Rr)f{{ӱ6Ն eW*;D)0>HVgXQNx wc q3::1&/:Ql(OP%_QMzcyA7ҝ<,\lY^FAOk[߯ SHtZZYDZ"㢉Lԩ>azX;V^:YmA6Q Fke,V#QdGy}`zU%ӕ>ް?j%Y467M+"`8DOMAOF~˿e*GC|c@\ELʯ{Z/Ri@˯Wcݬ66d$Xk#Jy@ g5F-V +3,/$zҒnZf-H?FQaXbe&#&%Z^wjOxáUs8詜dAx IDAT{{ڏMnŔbkuoYϋt)Hcpvx=InD3f&q6,*C~'Ţ-$Rkm B+glqFs8u 􈢊q0tPJ Lh2 FLgԭ'> H$|UbB3e9uJ%<\ƘrVf6}R0:~؃n ɪֲU@GrSd<E%lB YYbb)w.k+LvV5I?< \do4Oʝ-. c^tߘ{ p0FlmyoH7w ұa,dTM>aH00^~ XAqT K&Gx^PK8I!2A<3rXZ Y[EE'}m6u" ؜ p,BAkܳVo6YOk[wud%WN{=' h4 C)r#^QҤmpuh pZT*.CzZ:<O  eJN&tL8J%)uBUta׬lmyIR q4XBK0"ѣT1GL{%"z=U H?Ji\cAE{" RFUYe$dcC6/K[_6avYp/DgX1?++F#\s'#ml$-m)$ន6)!}OE7/IRټ'd HC'7$,uc3rd3'KRtu/ Ω.=Heci]a2٪SQEyroodaOjeAi"]si+ɉKAح뇼dst̝5 dZ5pP`Vlޠ '="ŢD4}KF؄,FCkbѬc$Up,Oea2Ӧl?kLvS, 3dGkbFCPAzݮP(P(:Hi/P-AjOu[17ug^Yno-kޑlof,.QԦQc"=WLLzhM/7SR.ZZMvD?,xZ?rl"%-+Ƭz8ꍍ:泓Ԍc5fb ,O(O+hbq{R^EceIFz=\ɹRonTBGĵȸ]vz6m23r2th H6%;Bgf{Qvh-ދ U3~;YW(.ۻghfZ5ّ q09lPd{=d USܵ+7\ٛ@M6l6ӣ!El:_Xw#ر ^_|ܵ2ِQFR7&H @rS'3+YUn7sT1aq\9 \eRoBa<dX%pdn}8D">?XE~6@.6Z1*ЅQ pp ̏ a.95'JF,>ҥ \]BpF^DJv㓦\ ɧRyP iX@PZ,{/SC4sstԧQ _۠z)>$ 8GWSA#N}Y,GJ;;{_mݥX)):RFJ+՗;)Yos6ƫJ-?B:e2Ϲsg |nGk-GG>a\]\PɒȆn#WW-vݲ/jNmhwwd^X,^vm M~(\b;ж+;>ufcu;Vj9F_^8g.< ELNݮicv 1Bk)[6٤ӑe U;ƺ>;r0kUїRvϊ 1@bCɏ~Zǡ@p-.p23{=b5^b v\NŅ:$;XI h~cH paYNWر"y"P'!sE_\%drܖv.bnb>y:7_VSzx(Щ?=E6zs)?ݿLrr : Eva=YIdV$lZrI9**``(EjN M[c8_-7V&Sx`Gtwg!E@]ʤ.kG-,weG6i8iҝݱcYa,3z^g}\^b??ƶ(6[ON,Ӑh-pXzrYeFEcJ<=2ʇH?v;c7'9NUM2*jeɢk,<@:*QGh$B>Y!|H>ta/#taP;Y nÎdAJnn9]ZuF(3,bA 'I<{%P",~y 2Qb|p_ sVElH P[_NVlv4R\H뵵BeۤaUj]>KQ Gk-L {Wի)ȅ:a3h[}d"{]-kPZ2σ`lw'&Pуn3:M wpj[4ݐ /WsgV5=.F#B$Ѕo7R?~n dNR9ٌ5x)@iHw@ve ?U-(RS6am3)o6;)+ewCi4ܯʢuV@_G39ezM73}tP^~ֿ?yJds~OJ}2xtSo(rsc(y(PHjqTۇ,~f@iɧOu]D@:\:-}f7;=dQۄIfč|apIRQfbNT?,OVZ,lNqPW6`<,Y0٦ohZrPoC.,} XH|6ClHg 0sj ƠX <1I%>L;2 Wu~݂uQ4û;ec|1Nik<օ)5u\)*پqtڨTEjn hW/WSʛj7/Vhazxk\34r c>eKJJ)eKh!V"}p̅l`7jV;:.hө<8k) 7 GG5:n'XOIBU"<_e@n?l2s8HԦa*7̒lĪvuvK=PB;!iĶ?]o@صw`6SUu MжCNJM-gV+ŗ/D9 7kcSoZ_]I&:ܾ+k4ZpJ_xcemv X3`?Y *Z@ҦFcRy) 5٦d6;X޿/tdpJ -Y>"ɲp#M6Esj5aL 3-?i.1h SJb!;<nu&`SF=Hڪtw(gSo&c'A] %}"N*G}^c`_`K+{w >^kDo-8)ZeCoQ:kJB"r\j-gÊl`2qɿHsV;MLߐ!(Itp=y&cujk]iU-|L:0ڑ'op٩ؤT-DTEJVޖ&&A :?zFA'hTע=mJŀԻL):.7]{ŌoQn_vo;նW~ϟeF)1Rfq;Zg_OƯ><:dv2e=c5S~xÍ5l5b r326A*RR}H qpwuseV(v:-^OX~Ro:.}ׯ7=3 [kb42*$$F8Nj4e 5Lv+rʒRa@(2lgvRa[4u4V%ͺ )iBa#'YgXyOM@xNPInunʕbvfݮ.fxLDihY.Em|5W i!HթWکY~eh!Fɵ v06,Cfo!˴y5, |}KԍmgaR| 06 $x_(3 V)QJs D ˏ5aq&)jJ?1LOOOirA~;U,k)-3 ɤl&JWʫ)TةHfSSx AS4;sEԐ2Y{6 6&n {> UJKF!םG(F+6ŒvCI)SeuTFբH hlEAw,lͼdH1/xdgN@෣. jr74'(3rp-ӚR)m2yIDAT(Yu>o g xKp]eGYQj h[\&A bB&kcDo@gq؎)pwe0f,ܣlcl^_w" * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal_formula.h * \brief Header file related to fractal formulas and loop iterations. * \author Marc Pegon */ #ifndef __FRACTAL_FORMULA_H__ #define __FRACTAL_FORMULA_H__ #include "float_precision.h" #include "complex_wrapper.h" #include #ifdef __cplusplus extern "C" { #endif /** * \enum e_FractalFormula * \brief Fractal formula. */ /** * \typedef FractalFormula * \brief Convenient typedef for enum e_FractalFormula. */ typedef enum e_FractalFormula { FRAC_MANDELBROT = 0, /*!< Mandelbrot fractal.*/ FRAC_MULTIBROT, /*!< Mandelbrot type fractal with custom p parameter.*/ FRAC_JULIA, /*!< Julia fractal.*/ FRAC_MULTIJULIA, /*!< Julia type fractal with custom p parameter.*/ FRAC_BURNINGSHIP, /*!< Burning ship.*/ FRAC_JULIABURNINGSHIP, /*!< Julia burning ship.*/ FRAC_MANDELBAR, /*!< Mandelbar.*/ FRAC_JULIABAR, /*!< Juliabar.*/ FRAC_RUDY /*!< Rudy fractal (with custom p parameter).*/ } FractalFormula; /** * \var nbFractalFormulas * \brief Number of fractal formulas. */ extern const uint_fast32_t nbFractalFormulas; /** * \var fractalFormulaStr * \brief Strings of fractal formulas. */ extern const char *fractalFormulaStr[]; /** * \var fractalFormulaDescStr * \brief More descriptive strings for fractal formulas. */ extern const char *fractalFormulaDescStr[]; /** * \fn int GetFractalFormula(FractalFormula *fractalFormula, const char *str) * \brief Get fractal formula from string. * * Function is case insensitive. * Possible strings are : * - "mandelbrot" for FRAC_MANDELBROT * - "mandelbrotp" for FRAC_MULTIBROT * - "julia" for FRAC_JULIA * - "juliap" for FRAC_JULIAP * - "burningship" for FRAC_BURNINGSHIP * - "juliaburningship" for FRAC_JULIABURNINGSHIP * - "mandelbar" for FRAC_MANDELBAR * - "juliabar" for FRAC_JULIABAR * - "rudy" for FRAC_RUDY * * \param fractalFormula Fractal formula destination. * \param str String specifying fractal formula. * \return 0 in case of success, 1 in case of failure. */ int GetFractalFormula(FractalFormula *fractalFormula, const char *str); #define cpowPINT(fprec,res,x,y) cipowF(fprec,res,x,y) #define cpowPFLOATT(fprec,res,x,y) cpowF(fprec,res,x,y) #define cpowPTYPE(ptype,fprec,res,x,y) cpow##ptype(fprec,res,x,y) #define fractalP_PINT data->fractalP_INT #define fractalP_PFLOATT data->fractalP #define fractalP(ptype) fractalP_##ptype /*********************FRAC_MANDELBROT*********************/ #define ENGINE_DECL_VAR_FRAC_MANDELBROT(fprec) #define ENGINE_INIT_VAR_FRAC_MANDELBROT(fprec) \ (void)NULL; #define ENGINE_CLEAR_VAR_FRAC_MANDELBROT(fprec) \ (void)NULL; #define LOOP_INIT_FRAC_MANDELBROT(fprec) \ cfromUiF(fprec, data->z, 0);\ cassignF(fprec, data->c, data->pixel); #define LOOP_ITERATION_FRAC_MANDELBROT(ptype,fprec) \ csqrF(fprec,data->z,data->z);\ caddF(fprec,data->z,data->z,data->c); /*********************************************************/ /**********************FRAC_MULTIBROT*********************/ #define ENGINE_DECL_VAR_FRAC_MULTIBROT(fprec) #define ENGINE_INIT_VAR_FRAC_MULTIBROT(fprec) \ (void)NULL; #define ENGINE_CLEAR_VAR_FRAC_MULTIBROT(fprec) \ (void)NULL; #define LOOP_INIT_FRAC_MULTIBROT(fprec) \ cfromUiF(fprec, data->z, 0);\ cassignF(fprec, data->c, data->pixel); #define LOOP_ITERATION_FRAC_MULTIBROT(ptype,fprec) \ cpowPTYPE(ptype,fprec,data->z,data->z,fractalP(ptype));\ caddF(fprec,data->z,data->z,data->c); /*********************************************************/ /***********************FRAC_JULIA************************/ #define ENGINE_DECL_VAR_FRAC_JULIA(fprec) #define ENGINE_INIT_VAR_FRAC_JULIA(fprec) \ (void)NULL; #define ENGINE_CLEAR_VAR_FRAC_JULIA(fprec) \ (void)NULL; #define LOOP_INIT_FRAC_JULIA(fprec) \ cassignF(fprec, data->z, data->pixel);\ cassignF(fprec, data->c, data->fractalC); #define LOOP_ITERATION_FRAC_JULIA(ptype,fprec) \ csqrF(fprec,data->z,data->z);\ caddF(fprec,data->z,data->z,data->c); /*********************************************************/ /*********************FRAC_MULTIJULIA*********************/ #define ENGINE_DECL_VAR_FRAC_MULTIJULIA(fprec) #define ENGINE_INIT_VAR_FRAC_MULTIJULIA(fprec) \ (void)NULL; #define ENGINE_CLEAR_VAR_FRAC_MULTIJULIA(fprec) \ (void)NULL; #define LOOP_INIT_FRAC_MULTIJULIA(fprec) \ cassignF(fprec, data->z, data->pixel);\ cassignF(fprec, data->c, data->fractalC); #define LOOP_ITERATION_FRAC_MULTIJULIA(ptype,fprec) \ cpowPTYPE(ptype,fprec,data->z,data->z,fractalP(ptype));\ caddF(fprec,data->z,data->z,data->c); /*********************************************************/ /*********************FRAC_BURNINGSHIP********************/ #define ENGINE_DECL_VAR_FRAC_BURNINGSHIP(fprec) \ FLOATTYPE(fprec) absRealZ_FRAC;\ FLOATTYPE(fprec) absImagZ_FRAC; #define ENGINE_INIT_VAR_FRAC_BURNINGSHIP(fprec) \ initF(fprec, data->absRealZ_FRAC);\ initF(fprec, data->absImagZ_FRAC); #define ENGINE_CLEAR_VAR_FRAC_BURNINGSHIP(fprec) \ clearF(fprec, data->absRealZ_FRAC);\ clearF(fprec, data->absImagZ_FRAC); #define LOOP_INIT_FRAC_BURNINGSHIP(fprec) \ cfromUiF(fprec, data->z, 0);\ cassignF(fprec, data->c, data->pixel); #define LOOP_ITERATION_FRAC_BURNINGSHIP(ptype,fprec) \ crealF(fprec, data->absRealZ_FRAC, data->z);\ fabsF(fprec, data->absRealZ_FRAC, data->absRealZ_FRAC);\ cimagF(fprec, data->absImagZ_FRAC, data->z);\ fabsF(fprec, data->absImagZ_FRAC, data->absImagZ_FRAC);\ cfromReImF(fprec, data->z, data->absRealZ_FRAC, data->absImagZ_FRAC);\ cpowPTYPE(ptype,fprec,data->z,data->z,fractalP(ptype));\ caddF(fprec,data->z,data->z,data->c); /*********************************************************/ /*******************FRAC_JULIABURNINGSHIP******************/ #define ENGINE_DECL_VAR_FRAC_JULIABURNINGSHIP(fprec) \ FLOATTYPE(fprec) absRealZ_FRAC;\ FLOATTYPE(fprec) absImagZ_FRAC; #define ENGINE_INIT_VAR_FRAC_JULIABURNINGSHIP(fprec) \ initF(fprec, data->absRealZ_FRAC);\ initF(fprec, data->absImagZ_FRAC); #define ENGINE_CLEAR_VAR_FRAC_JULIABURNINGSHIP(fprec) \ clearF(fprec, data->absRealZ_FRAC);\ clearF(fprec, data->absImagZ_FRAC); #define LOOP_INIT_FRAC_JULIABURNINGSHIP(fprec) \ cassignF(fprec, data->z, data->pixel);\ cassignF(fprec, data->c, data->fractalC); #define LOOP_ITERATION_FRAC_JULIABURNINGSHIP(ptype,fprec) \ crealF(fprec, data->absRealZ_FRAC, data->z);\ fabsF(fprec, data->absRealZ_FRAC, data->absRealZ_FRAC);\ cimagF(fprec, data->absImagZ_FRAC, data->z);\ fabsF(fprec, data->absImagZ_FRAC, data->absImagZ_FRAC);\ cfromReImF(fprec, data->z, data->absRealZ_FRAC, data->absImagZ_FRAC);\ cpowPTYPE(ptype,fprec,data->z,data->z,fractalP(ptype));\ caddF(fprec,data->z,data->z,data->c); /*********************************************************/ /**********************FRAC_MANDELBAR*********************/ #define ENGINE_DECL_VAR_FRAC_MANDELBAR(fprec) #define ENGINE_INIT_VAR_FRAC_MANDELBAR(fprec) \ (void)NULL; #define ENGINE_CLEAR_VAR_FRAC_MANDELBAR(fprec) \ (void)NULL; #define LOOP_INIT_FRAC_MANDELBAR(fprec) \ cfromUiF(fprec, data->z, 0);\ cassignF(fprec, data->c, data->pixel); #define LOOP_ITERATION_FRAC_MANDELBAR(ptype,fprec) \ conjF(fprec, data->z, data->z);\ cpowPTYPE(ptype,fprec,data->z,data->z,fractalP(ptype));\ caddF(fprec,data->z,data->z,data->c); /*********************************************************/ /**********************FRAC_JULIABAR**********************/ #define ENGINE_DECL_VAR_FRAC_JULIABAR(fprec) #define ENGINE_INIT_VAR_FRAC_JULIABAR(fprec) \ (void)NULL; #define ENGINE_CLEAR_VAR_FRAC_JULIABAR(fprec) \ (void)NULL; #define LOOP_INIT_FRAC_JULIABAR(fprec) \ cassignF(fprec, data->z, data->pixel);\ cassignF(fprec, data->c, data->fractalC); #define LOOP_ITERATION_FRAC_JULIABAR(ptype,fprec) \ conjF(fprec, data->z, data->z);\ cpowPTYPE(ptype,fprec,data->z,data->z,fractalP(ptype));\ caddF(fprec,data->z,data->z,data->c); /*********************************************************/ /************************FRAC_RUDY************************/ #define ENGINE_DECL_VAR_FRAC_RUDY(fprec) \ COMPLEX_FLOATTYPE(fprec) cz_FRAC; #define ENGINE_INIT_VAR_FRAC_RUDY(fprec) \ cinitF(fprec, data->cz_FRAC); #define ENGINE_CLEAR_VAR_FRAC_RUDY(fprec) \ cclearF(fprec, data->cz_FRAC); #define LOOP_INIT_FRAC_RUDY(fprec) \ cfromUiF(fprec, data->z, 0);\ cassignF(fprec, data->c, data->pixel); #define LOOP_ITERATION_FRAC_RUDY(ptype,fprec) \ cmulF(fprec, data->cz_FRAC, data->fractalC, data->z);\ cpowPTYPE(ptype,fprec,data->z,data->z,fractalP(ptype));\ caddF(fprec,data->z,data->z,data->cz_FRAC);\ caddF(fprec,data->z,data->z,data->c);\ /*********************************************************/ #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/gui/include/main.h000664 001750 001750 00000003157 13175112471 017121 0ustar00mpegmpeg000000 000000 /* * main.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file main.h * \brief Header file related to QFractalNow program. * \author Marc Pegon */ #ifndef __MAIN_H__ #define __MAIN_H__ #include /* Fractal is anti-aliased iteratively from "minimum anti-aliasing size" * to "maximum anti-aliasing size" by steps of "anti-aliasing size iteration". */ //! Default minimum anti-aliasing size. #define DEFAULT_MIN_ANTIALIASING_SIZE (uint_fast32_t)(3) //! Default maximum anti-aliasing size. #define DEFAULT_MAX_ANTIALIASING_SIZE (uint_fast32_t)(3) //! Default anti-aliasing size iteration. #define DEFAULT_ANTIALIASING_SIZE_ITERATION (uint_fast32_t)(2) //! Default number of decimals. #define DEFAULT_DECIMALS_NUMBER (int)(20) //! Minimum SingleStep for double & mpfr spin boxes. #define MIN_SINGLE_STEP (double)(pow(10, -DBL_DIG)) #endif fractalnow-0.8.2/lib/src/gradient.c000664 001750 001750 00000030135 13175115345 017112 0ustar00mpegmpeg000000 000000 /* * gradient.c -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "gradient.h" #include "error.h" #include "file_io.h" #include "misc.h" #include const char *gradientFormatStr[] = { (const char *)"g073" }; const uint_fast32_t nbGradientFormats = sizeof(gradientFormatStr) / sizeof(const char *); int ReadGradientFileV073(Gradient *gradient, uint_fast8_t bytesPerComponent, const char *fileName, FILE *file); typedef int (*ReadGradientFileFunction)(Gradient *gradient, uint_fast8_t bytesPerComponent, const char *fileName, FILE *file); const ReadGradientFileFunction readGradientFileFunction[] = { ReadGradientFileV073 }; int WriteGradientFileV073(const Gradient *gradient, const char *fileName, FILE *file); typedef int (*WriteGradientFileFunction)(const Gradient *gradient, const char *fileName, FILE *file); const WriteGradientFileFunction writeGradientFileFunction[] = { WriteGradientFileV073 }; void aux_GenerateGradient(Gradient *gradient, uint_fast64_t begin_ind_tab, uint_fast64_t end_ind_tab, Color C1, Color C2) { uint_fast64_t N = end_ind_tab - begin_ind_tab; Color *pixel = gradient->data+begin_ind_tab; if (N == 0) { *pixel = C2; } else { for (uint_fast64_t i=0;i<=N;i++) { pixel->bytesPerComponent = C1.bytesPerComponent; pixel->r = (C1.r*(N-i) + C2.r*i) / N; pixel->g = (C1.g*(N-i) + C2.g*i) / N; pixel->b = (C1.b*(N-i) + C2.b*i) / N; ++pixel; } } } void GenerateGradient(Gradient *gradient, uint_fast32_t nbStops, double *positionStop, Color *colorStop, uint_fast32_t size) { FractalNow_message(stdout, T_NORMAL,"Generating gradient...\n"); if (nbStops < 2) { FractalNow_error("Gradient number of stops must be >= 2.\n"); } if (size == 0) { FractalNow_error("Gradient size must be > 0.\n"); } gradient->positionStop = (double *)safeMalloc("position stops copy", nbStops*sizeof(double)); memcpy(gradient->positionStop, positionStop, nbStops*sizeof(double)); gradient->colorStop = (Color *)safeMalloc("color stops copy", nbStops*sizeof(Color)); memcpy(gradient->colorStop, colorStop, nbStops*sizeof(Color)); gradient->nbStops = nbStops; gradient->bytesPerComponent = colorStop[0].bytesPerComponent; gradient->size = size; gradient->data = (Color *)safeMalloc("gradient data", size*sizeof(Color)); for (uint_fast32_t i=0; i 1) { FractalNow_error("Gradient position stops must be between 0 and 1.\n"); } else if (i != 0 && positionStop[i] <= positionStop[i-1]) { FractalNow_error("Gradient position stops should be (stricly) increasing.\n"); } aux_GenerateGradient(gradient, positionStop[i]*(size-1), positionStop[i+1]*(size-1), colorStop[i], colorStop[i+1]); } FractalNow_message(stdout, T_NORMAL,"Generating gradient : DONE.\n"); } void GenerateGradient2(Gradient *gradient, uint_fast32_t nbStops, Color *colorStop, uint_fast32_t nbTransitions) { if (nbTransitions == 0) { FractalNow_error("Gradient number of transitions must be > 0.\n"); } double *positionStop = (double *)malloc(nbStops * sizeof(double)); for (uint_fast32_t i = 0; i < nbStops; ++i) { positionStop[i] = i / (double)(nbStops-1); } uint_fast64_t size = (nbStops-1) * nbTransitions; GenerateGradient(gradient, nbStops, positionStop, colorStop, size); free(positionStop); } Gradient CopyGradient(const Gradient *gradient) { Gradient res; res.bytesPerComponent = gradient->bytesPerComponent; res.size = gradient->size; res.data = (Color *)safeMalloc("gradient copy data", gradient->size*sizeof(Color)); memcpy(res.data, gradient->data, gradient->size*sizeof(Color)); res.nbStops = gradient->nbStops; res.positionStop = (double *)safeMalloc("gradient position stop copy", gradient->nbStops*sizeof(double)); memcpy(res.positionStop, gradient->positionStop, gradient->nbStops*sizeof(double)); res.colorStop = (Color *)safeMalloc("gradient color stop copy", gradient->nbStops*sizeof(Color)); memcpy(res.colorStop, gradient->colorStop, gradient->nbStops*sizeof(Color)); return res; } Gradient Gradient16(const Gradient *gradient) { Gradient res; if (gradient->bytesPerComponent == 2) { res = CopyGradient(gradient); } else { Color *tmp = (Color *)safeMalloc("16 bits gradient color stops copy", gradient->nbStops*sizeof(Color)); for (uint_fast32_t i = 0; i < gradient->nbStops; ++i) { tmp[i] = Color16(gradient->colorStop[i]); } GenerateGradient(&res, gradient->nbStops, gradient->positionStop, tmp, gradient->size); free(tmp); } return res; } Gradient Gradient8(const Gradient *gradient) { Gradient res; if (gradient->bytesPerComponent == 1) { res = CopyGradient(gradient); } else { Color *tmp = (Color *)safeMalloc("8 bits gradient color stops copy", gradient->nbStops*sizeof(Color)); for (uint_fast32_t i = 0; i < gradient->nbStops; ++i) { tmp[i] = Color8(gradient->colorStop[i]); } GenerateGradient(&res, gradient->nbStops, gradient->positionStop, tmp, gradient->size); free(tmp); } return res; } inline Color GetGradientColor(const Gradient *gradient, uint_fast64_t index) { return gradient->data[index % gradient->size]; } void FreeGradient(Gradient gradient) { free(gradient.data); free(gradient.positionStop); free(gradient.colorStop); } int ReadGradientFileV073(Gradient *gradient, uint_fast8_t bytesPerComponent, const char *fileName, FILE *file) { int res = 0; double positionStop[257]; Color colorStop[257]; uint_fast32_t nbStops=0; int readRes; while (1) { readRes = readDouble(file, &positionStop[nbStops]); if (readRes == EOF) { break; } else if (readRes != 1) { FractalNow_read_werror(fileName); } readRes = readColor(file, bytesPerComponent, &colorStop[nbStops]); if (readRes == EOF) { FractalNow_werror("Missing gradient color stop.\n"); } else if (readRes != 1) { FractalNow_read_werror(fileName); } if (nbStops > 255) { break; } nbStops++; } if (nbStops < 2 || nbStops > 255) { FractalNow_werror("Gradient number of stops must be between 2 and 255.\n"); } /* Check stops are well-formed (pos0 = 0 <= pos1 <= ... <= posN = 1) */ if (positionStop[0] != 0) { FractalNow_werror("First gradient stop position should be 0.\n"); } if (positionStop[nbStops-1] != 1) { FractalNow_werror("Last gradient stop position should be 1.\n"); } for (uint_fast32_t i = 1; i < nbStops; ++i) { if (positionStop[i] <= positionStop[i-1]) { FractalNow_werror("Gradient stop positions should be (stricly) increasing.\n"); } } GenerateGradient(gradient, nbStops, positionStop, colorStop, DEFAULT_GRADIENT_SIZE); end: return res; } ReadGradientFileFunction GetReadGradientFileFunction(const char *format) { if (strlen(format) != 4) { return NULL; } ReadGradientFileFunction readGradientFile = NULL; char formatStr[5]; strcpy(formatStr, format); toLowerCase(formatStr); uint_fast32_t i; for (i = 0; i < nbGradientFormats; ++i) { if (strcmp(formatStr, gradientFormatStr[i]) == 0) { readGradientFile = readGradientFileFunction[i]; break; } } return readGradientFile; } int isSupportedGradientFile(const char *fileName) { int res = 0; FILE *file; file=fopen(fileName,"r"); if (!file) { FractalNow_open_werror(fileName); } char formatStr[256]; if (readString(file, formatStr) < 1) { res = 1; } else { ReadGradientFileFunction readGradientFileFunction; readGradientFileFunction = GetReadGradientFileFunction(formatStr); res = (readGradientFileFunction == NULL); } end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } return !res; } int ReadGradientFileBody(Gradient *gradient, uint_fast8_t bytesPerComponent, const char *fileName, FILE *file, const char *format) { FractalNow_message(stdout, T_VERBOSE, "Reading gradient file body...\n"); int res = 0; ReadGradientFileFunction readGradientFile; readGradientFile = GetReadGradientFileFunction(format); if (readGradientFile == NULL) { FractalNow_werror("Unsupported gradient format '%s'.\n", format); } res |= readGradientFile(gradient, bytesPerComponent, fileName, file); end: FractalNow_message(stdout, T_VERBOSE, "Reading gradient file body : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } int ReadGradientFile(Gradient *gradient, const char *fileName) { FractalNow_message(stdout, T_NORMAL, "Reading gradient file...\n"); int res = 0; FILE *file; file=fopen(fileName,"r"); if (!file) { FractalNow_open_werror(fileName); } char formatStr[256]; if (readString(file, formatStr) < 1) { FractalNow_read_werror(fileName); } uint_fast8_t bytesPerComponent; uint32_t bytesPerComponent32; if (readUint32(file, &bytesPerComponent32) < 1) { FractalNow_read_werror(fileName); } if (bytesPerComponent32 == 1 || bytesPerComponent32 == 2) { bytesPerComponent = (uint_fast8_t)bytesPerComponent32; } else { FractalNow_werror("Invalid gradient file : bytes per components must be 1 or 2.\n"); } res = ReadGradientFileBody(gradient, bytesPerComponent, fileName, file, formatStr); end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } FractalNow_message(stdout, T_NORMAL, "Reading gradient file : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } int WriteGradientFileV073(const Gradient *gradient, const char *fileName, FILE *file) { int res = 0; const char *suffix = " "; for (uint_fast32_t i = 0; i < gradient->nbStops; ++i) { if (writeDouble(file, gradient->positionStop[i], " ") < 0) { FractalNow_write_werror(fileName); } if (i == gradient->nbStops-1) { suffix = "\n"; } if (writeColor(file, gradient->colorStop[i], suffix) < 0) { FractalNow_write_werror(fileName); } } end: return res; } WriteGradientFileFunction GetWriteGradientFileFunction(const char *format) { if (strlen(format) != 4) { return NULL; } WriteGradientFileFunction writeGradientFile = NULL; char formatStr[5]; strcpy(formatStr, format); toLowerCase(formatStr); uint_fast32_t i; for (i = 0; i < nbGradientFormats; ++i) { if (strcmp(formatStr, gradientFormatStr[i]) == 0) { writeGradientFile = writeGradientFileFunction[i]; break; } } return writeGradientFile; } int WriteGradientFileBody(const Gradient *gradient, const char *fileName, FILE *file, const char *format) { FractalNow_message(stdout, T_VERBOSE, "Writing gradient file body...\n"); int res = 0; WriteGradientFileFunction writeGradientFile; writeGradientFile = GetWriteGradientFileFunction(format); if (writeGradientFile == NULL) { FractalNow_werror("Unsupported gradient format '%s'.\n", format); } res |= writeGradientFile(gradient, fileName, file); end: FractalNow_message(stdout, T_VERBOSE, "Writing gradient file body : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } int WriteGradientFile(const Gradient *gradient, const char *fileName) { FractalNow_message(stdout, T_NORMAL, "Writing gradient file...\n"); int res = 0; FILE *file; file=fopen(fileName,"w"); if (!file) { FractalNow_open_werror(fileName); } const char *format = gradientFormatStr[nbGradientFormats-1]; if (writeString(file, format, "\n") < 0) { FractalNow_write_werror(fileName); } if (writeUint32(file, gradient->bytesPerComponent, "\n") < 0) { FractalNow_write_werror(fileName); } res |= WriteGradientFileBody(gradient, fileName, file, format); end: if (file && fclose(file)) { FractalNow_close_errmsg(fileName); res = 1; } FractalNow_message(stdout, T_VERBOSE, "Writing gradient file body : %s.\n", (res == 0) ? "DONE" : "FAILED"); return res; } fractalnow-0.8.2/examples/config_files/config09.config000664 001750 001750 00000000306 13175112471 022660 0ustar00mpegmpeg000000 000000 c075 julia 0.285 0.01 0 0 2.47464114832536 2.47464114832536 10000000 1000 1 0x0 averagecoloring triangleinequality linear squareroot 1.3 0 0 0x39a0 0.25 0xffffff 0.5 0xfffe43 0.75 0xbf0800 1 0x39a0 fractalnow-0.8.2/gui/src/color_button.cpp000664 001750 001750 00000003001 13175112471 020371 0ustar00mpegmpeg000000 000000 /* * color_button.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "color_button.h" void ColorButton::updateIcon() { QPixmap pixmap(sizeHint()); pixmap.fill(color); QIcon icon(pixmap); setIcon(icon); } ColorButton::ColorButton(QWidget *parent) : QPushButton(parent) { color = Qt::white; updateIcon(); colorDialog = new QColorDialog(this); connect(this, SIGNAL(clicked()), this, SLOT(openColorDialog())); } const QColor &ColorButton::currentColor() const { return color; } void ColorButton::setCurrentColor(const QColor &color) { if (color != this->color) { this->color = color; updateIcon(); emit currentColorChanged(color); } } void ColorButton::openColorDialog() { colorDialog->open(this, SLOT(setCurrentColor(QColor))); } fractalnow-0.8.2/lib/include/task.h000664 001750 001750 00000024267 13175112471 017126 0ustar00mpegmpeg000000 000000 /* * task.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file task.h * \brief Header file related to tasks. * \author Marc Pegon */ #ifndef __TASKS_H__ #define __TASKS_H__ #include "thread.h" #ifdef __cplusplus extern "C" { #endif struct Task; /** * \struct CompositeTaskArguments * \brief Arguments structure for composite tasks thread routine. * * This is for internal use only. */ /** * \typedef CompositeTaskArguments * \brief Convenient typedef for struct CompositeTaskArguments. */ typedef struct CompositeTaskArguments { struct Task *thisTask; /*!< Pointer to the composite task being run.*/ } CompositeTaskArguments; /** * \struct Task * \brief Structure to control tasks execution by threads. * * Typically, executing a task by threads is done in 3 * steps: * -create task * -launch task * -wait for it to finish * * Through the task structure, it is possible to cancel * a task, to pause it and then resume it, as well to wait for * it to finish (get task result). * * Some examples of use :\n * 1) Launch task and wait for it to finish :\n * task = CreateTask(message, threads, nbThreadsNeeded, * args, s_elem, routine, freeArgs);\n * LaunchTask(task, threads);\n * res = GetTaskResult(task); * * 2) Launch threads, cancel task after some time, wait for it to * finish.\n * task = CreateTask(message, threads, nbThreadsNeeded, args, s_elem, routine, freeArgs);\n * sleep(2);\n * CancelTask(task); // (send cancelation request)\n * res = GetTaskResult(task); // wait for it to finish\n * * It is up to the thread routine to take into account cancellation * request and finish earlier, via the CancelRequested function. * * Remark: note that although the functions described here deal * with threads, they are not thread-safe (like all the functions * in this library btw), i.e. the functions here should not be run * concurrently by different threads (although, if necessary, it * would be quite easy to make them thread-safe, by adding a mutex * for each function). */ /** * \typedef Task * \brief Convenient typedef for struct Task. */ typedef struct Task { int isComposite; /*!< 1 if task consists of a sequence of subtasks.*/ int launchPrepared; /*!< 1 if launch has been prepared (for composite tasks).*/ int hasBeenLaunched; /*!< 1 if created task has already been launched.*/ int done; /*!< 1 if task has already finished and threads have been joined.*/ int returnValue; /*!< Task return value (0 if finished normally, 1 if canceled).*/ int cancel; /*!< Integer used for cancellation request.*/ pthread_spinlock_t cancelMutex; /*!< Mutex for cancel variable.*/ int pause; /*!< Integer used to pause task.*/ pthread_spinlock_t pauseMutex; /*!< Mutex for pause variable.*/ /* For composite tasks: */ CompositeTaskArguments compositeTaskArguments; /*!< Arguments for composite tasks.*/ uint_fast32_t nbSubTasks; /*!< Number of subtasks (for composite task only).*/ struct Task **subTasks; /*!< Subtasks (for composite task only).*/ uint_fast32_t compositeTaskNbReady; /*!< Number of threads ready to launch a new subtask.*/ int stopLaunchingSubTasks; /*!< Instructs composite task routine to stop launching subtasks (cancel requested).*/ pthread_cond_t compositeTaskAllThreadsReadyCond; /*!< Signaled when all threads are ready to launch new subtask.*/ /* For non-composite tasks: */ struct ThreadArgHeader *threadArgsHeaders; /*!< Internal part of thread arguments (cancel and progress handling).*/ struct Threads *threads; /*!< Pointer to threads to use for task.*/ uint_fast32_t nbThreadsNeeded; /*!< Number of threads actually needed for task.*/ void *initialArgs; /*!< Copy of initial arguments (as passed to CreateTask).*/ void *args; /*!< Array of args passed to thread routine (with headers).*/ size_t s_elem; /*!< Size of each argument.*/ void *(*threadsRoutine)(void *); /*!< Task routine (to be executed by each thread).*/ void (*freeArg)(void *); /*!< Routine to free each arg.*/ char *message; /*!< Task message to print at launch and when it finishes.*/ } Task; /** * \fn Task *DoNothingTask() * \brief Returns a newly-allocated task that does nothing. * * Convenient for working on empty image for example. * * \return Do-nothing task. */ Task *DoNothingTask(); /** * \fn Task *CreateTask(const char message[], uint_fast32_t nbThreadsNeeded, const void *args, size_t s_elem, void *(*routine)(void *), void (*freeArg)(void *)) * \brief Create task. * * args is copied.\n * Note that arguments passed to the thread routine are not * exactly those passed to the function :\n * A ThreadArgHeader structure is added at the beginning of the * argument, which should be used to handle cancellation requests and * task progress.\n * The remaining bytes are the 'real' argument.\n * Free argument routine will be called for each argument when task * is free'd (can be NULL if arguments contain no dynamically * allocated data). * * \param message Task message to print at launch and when task finishes. * \param nbThreadsNeeded Number of threads needed to launch task. * \param args Pointer to array of arguments for threads routines. * \param s_elem Size of one argument (in bytes). * \param routine Threads routine. * \param freeArg Routine to free each argument. * \return Corresponding newly-allocated task. */ Task *CreateTask(const char message[], uint_fast32_t nbThreadsNeeded, const void *args, size_t s_elem, void *(*routine)(void *), void (*freeArg)(void *)); /** * \fn Task *CreateCompositeTask(const char message[], uint_fast32_t nbSubTasks, Task *subTasks[]) * \brief Create composite task. * * Create a "virtual" task made of subtasks.\n * Array of subtasks pointers will be copied (though not the tasks * themselves). * * \param message Task message to print at launch and when task finishes. * \param nbSubTasks Number of subtasks. * \param subTasks Array of subtasks. * \return Newly-allocated composite task. */ Task *CreateCompositeTask(const char message[], uint_fast32_t nbSubTasks, Task *subTasks[]); /** * \fn void LaunchTask(Task *task, Threads *threads) * \brief Launch task. * * Exit with error if task has already been launched.\n * Exit with error if number of threads needed for task * is greater than number of threads.\n * Threads should *not* be busy when calling this * function (unspecified behaviour otherwise). * * \param task Task to be launched. * \param threads Threads that will execute task. */ void LaunchTask(Task *task, Threads *threads); /** * \fn int ExecuteTaskBlocking(Task *task, Threads *threads) * \brief Execute task (blocking). * * Launch task and wait for it finish before returning. * \see LaunchTask * * \param task Task to be executed. * \param threads Threads that will be used to execute task. * \return Task return value (0 if finished normally, 1 if cancelled); */ int ExecuteTaskBlocking(Task *task, Threads *threads); /** * \fn int TaskIsFinished(Task *task) * \brief Test if task is finished. * * A not-yet-launched task is considered not finished * (0 returned). * * \param task Task to be tested. * \return 1 if task is finished, 0 otherwise. */ int TaskIsFinished(Task *task); /** * \fn int GetTaskResult(Task *task) * \brief Get task result. * * Exit with error if task has not been launched yet.\n * If task has already been launched but is not finished,\n * the function will block until it is finished.\n * Hence make sure that task is not paused when calling\n * this function (deadlock). * * \param task Task to finish. * \return 0 if task finished normally, 1 if it was cancelled, -1 if it has not yet been launched. */ int GetTaskResult(Task *task); /** * \fn void CancelTask(Task *task) * \brief Send cancelation request to task. * * Note that the function returns immediately after * sending the cancelation request. * You can call GetTaskResult after CancelTask to * make sure it is effectively canceled.\n * It is up to the task routine to take the request into * account, via the CancelRequested function.\n * \see CancelRequested * Does nothing if task has already finished.\n * * \param task Task to send cancellation request to. */ void CancelTask(Task *task); /** \fn void PauseTask(Task *task) * \brief Pause task. * * Function returns after task has effectively been paused * (unlike CancelAction which only sends a request).\n * You can use this function to access data being modified * by task safely.\n * Does nothing if task is already paused, has not been launched * yet, or has already finished. * * \brief task Task to be paused. */ void PauseTask(Task *task); /** \fn void ResumeTask(Task *task) * \brief Resume task. * * Resume task after it has been paused.\n * Does nothing if task has not been launched yet, * or has already finished. */ void ResumeTask(Task *task); /** * \fn double GetTaskProgress(const Task *task) * \brief Get task progress. * * Progress is a value between 0 (just begun) and 1 (done).\n * Returns 0 if task has not been launched yet. * * \param task Task subject to request. * \return Task progress. */ double GetTaskProgress(const Task *task); /** * \fn void FreeTask(Task *task) * \brief Free task data. * * If task has been launched, it *must* have already finished: * exit with error otherwise.\n * Note: a prior call to GetTaskResult will ensure that task * has finished, since it waits for action to finish. * * \param task Task to be free'd. */ void FreeTask(Task *task); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/config_files/config16.config000664 001750 001750 00000000302 13175112471 022652 0ustar00mpegmpeg000000 000000 C075 MANDELBROT -0.743643887037151 0.131825904205330 5.1299E-11 5.1299E-11 128. 7500 1 0x0 ITERATIONCOUNT SMOOTH SQUAREROOT 3.0E-2 0 0 0x39A0 0.25 0xFFFFFF 0.5 0xFFFE43 0.75 0xBF0800 1 0x39A0 fractalnow-0.8.2/INSTALL000664 001750 001750 00000003037 13175112471 014643 0ustar00mpegmpeg000000 000000 Installation ============ Requirements: * Qt 4.7.0 or newer * MPC 0.8 or newer * MPFR 3.0.0 or newer (consistent with MPC) * GMP library (consistent with MPFR) Note that Qt is only needed for the graphical tool, QFractalNow. Linux ===== You will need gcc to build the command-line tool (although any C99 compiler would do, just edit the CC variable in Makefile.configure files from lib and command-line directories) and a modern C++ compiler (preferably g++) to build the graphical tool. The typical procedure for building and installing FractalNow is: $ ./configure $ make # make install This will install FractalNow in /usr/local. See configure help for more options: $ ./configure -h Windows ======= The easiest way to build FractalNow for Windows is to use MSYS and mingw. Make sure MPC, MPFR, and GMP are correctly installed in your mingw directory (most mingw builds do not include them, so you will probably have to build them yourself). Make sure MSYS is configured correctly to find your mingw installation (run /postinstall/pi.sh if it is not the case). Under MSYS, add Qt binary directory to your path, and then type: $ ./configure $ make $ make install This will install FractalNow in ./install_dir. The configure script will normally detect that you are running MSYS on Windows and install (i.e. copy) the needed Qt DLLs (if Qt was not compiled statically) as well. You may have to add some other DLLs manually (e.g. pthread, gmp, mpfr, and mpc libraries if not linked statically). See configure help for more options: $ ./configure -h fractalnow-0.8.2/lib/include/fractal_transfer_function.h000664 001750 001750 00000006304 13175112471 023401 0ustar00mpegmpeg000000 000000 /* * fractal_transfer_function.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal_transfer_function.h * \brief Header file related to fractal transfer functions. * \author Marc Pegon */ #ifndef __FRACTAL_TRANSFER_FUNCTION_H__ #define __FRACTAL_TRANSFER_FUNCTION_H__ #include #ifdef __cplusplus extern "C" { #endif /** * \enum e_TransferFunction * \brief Possible transfer functions. * * Transfer function are used to map fractal values to colors correctly. */ /** * \typedef TransferFunction * \brief Convenient typedef for enum TransferFunction. */ typedef enum e_TransferFunction { TF_LOGLOG = 0, /* * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file command_line.h * \brief Header file related to command line parsing. * \author Marc Pegon */ #ifndef __COMMAND_LINE_H__ #define __COMMAND_LINE_H__ #include "main.h" #include "fractalnow.h" #include //! For storing command lines arguments. /* This structure is to store the arguments given on the command line. */ class CommandLineArguments { public: //!brief Parse arguments given on command line. /* * \param dst Pointer to the (already allocated) structure in which to store the arguments. * \param argc Argc of the main function * \param argv Argv of the main function */ CommandLineArguments(int argc, char *argv[]); //! Config file name. char *fractalConfigFileName; //! Fractal file name. char *fractalFileName; //! Rendering file name. char *renderingFileName; //! Rendering file name. char *gradientFileName; //! Width of output float table/image. uint_fast32_t width; //! Height of output float table/image. uint_fast32_t height; //! Minimum size for anti-aliasing. uint_fast32_t minAntiAliasingSize; //! Maximum size for anti-aliasing. uint_fast32_t maxAntiAliasingSize; //! Anti-aliasing size iteration. uint_fast32_t antiAliasingSizeIteration; //! Force number of threads used for drawing fractals. int nbThreads; //! Quad interpolation size. uint_fast32_t quadInterpolationSize; //! Adaptive anti-aliasing threshold. double adaptiveAAMThreshold; //! Color dissimilarity threshold. double colorDissimilarityThreshold; //! Float precision for computing fractal. FloatPrecision floatPrecision; #ifdef _ENABLE_MP_FLOATS //! Precision (value) of Multiple Precision floats. int64_t MPFloatPrecision; #endif }; #endif fractalnow-0.8.2/lib/src/builtin_complex.c000664 001750 001750 00000007266 13175115345 020523 0ustar00mpegmpeg000000 000000 /* * builtin_complex.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "builtin_complex.h" #ifdef BUILD_COMPLEX #undef BUILD_COMPLEX #endif #define BUILD_COMPLEX(type, suffix) \ inline Complex_##suffix cbuild_##suffix(type re, type im)\ {\ Complex_##suffix res = { re, im };\ \ return res;\ }\ \ inline int ceq_##suffix(Complex_##suffix a, Complex_##suffix b)\ {\ return (a.re == b.re) && (a.im == b.im);\ }\ \ inline type creal_##suffix(Complex_##suffix a)\ {\ return a.re;\ }\ \ inline type cimag_##suffix(Complex_##suffix a)\ {\ return a.im;\ }\ \ inline Complex_##suffix conj_##suffix(Complex_##suffix a)\ {\ return cbuild_##suffix(a.re, -a.im);\ }\ \ inline type cnorm_##suffix(Complex_##suffix a)\ {\ return (a.re*a.re)+(a.im*a.im);\ }\ \ inline type cabs_##suffix(Complex_##suffix a)\ {\ return sqrt##suffix(cnorm_##suffix(a));\ }\ \ inline Complex_##suffix cadd_##suffix(Complex_##suffix a, Complex_##suffix b)\ {\ return cbuild_##suffix(a.re+b.re, a.im+b.im);\ }\ \ inline Complex_##suffix csub_##suffix(Complex_##suffix a, Complex_##suffix b)\ {\ return cbuild_##suffix(a.re-b.re, a.im-b.im);\ }\ \ inline Complex_##suffix csqr_##suffix(Complex_##suffix a)\ {\ type re2 = a.re*a.re;\ type im2 = a.im*a.im;\ type re_x_im = a.re*a.im;\ \ return cbuild_##suffix(re2-im2, 2*re_x_im);\ }\ \ inline Complex_##suffix cmul_##suffix(Complex_##suffix a, Complex_##suffix b)\ {\ return cbuild_##suffix(a.re*b.re-a.im*b.im, a.re*b.im+b.re*a.im);\ }\ \ inline Complex_##suffix cdiv_##suffix(Complex_##suffix a, Complex_##suffix b)\ {\ Complex_##suffix tmp = cmul_##suffix(a, conj_##suffix(b));\ \ type norm = cnorm_##suffix(b);\ \ return cbuild_##suffix(tmp.re/norm, tmp.im/norm);\ }\ \ inline type carg_##suffix(Complex_##suffix a)\ {\ return atan2##suffix(a.im, a.re);\ }\ \ inline Complex_##suffix cexp_##suffix(Complex_##suffix a)\ {\ type exp_re = exp##suffix(a.re);\ return cbuild_##suffix(exp_re*cos##suffix(a.im), exp_re*sin##suffix(a.im));\ }\ \ inline Complex_##suffix clog_##suffix(Complex_##suffix a)\ {\ return cbuild_##suffix(log##suffix(cabs_##suffix(a)), carg_##suffix(a));\ }\ \ inline Complex_##suffix cipow_##suffix(Complex_##suffix x, uint_fast32_t y)\ {\ Complex_##suffix res;\ \ if (y == 0) {\ res = cbuild_##suffix(1, 0);\ }\ \ Complex_##suffix rem = cbuild_##suffix(1, 0);\ res = x;\ while (y > 1) {\ if (y % 2) {\ rem = cmul_##suffix(rem, res);\ --y;\ }\ y >>= 1;\ res = csqr_##suffix(res);\ }\ \ res = cmul_##suffix(res, rem);\ \ return res;\ }\ \ inline Complex_##suffix cpow_##suffix(Complex_##suffix a, Complex_##suffix b)\ {\ return cexp_##suffix(cmul_##suffix(b, clog_##suffix(a)));\ }\ \ inline int cisinteger_##suffix(Complex_##suffix x)\ {\ if (cimag_##suffix(x) != 0) {\ return 0;\ } else {\ type fptr, iptr;\ fptr = modf##suffix(creal_##suffix(x), &iptr);\ \ return (fptr == 0);\ }\ } BUILD_COMPLEX(float, f) BUILD_COMPLEX(double, ) BUILD_COMPLEX(long double, l) #undef BUILD_COMPLEX fractalnow-0.8.2/examples/rendering_files/render04d.render000664 001750 001750 00000000122 13175112471 023547 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING STRIPE 3 LINEAR CUBE 1 0 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/gui/include/gradient_box.h000664 001750 001750 00000003161 13175112471 020635 0ustar00mpegmpeg000000 000000 /* * gradient_box.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file gradient_box.h * \brief Header file introducing MainWindow class. * * \author Marc Pegon */ #ifndef __GRADIENT_BOX_H__ #define __GRADIENT_BOX_H__ #include "gradient_label.h" #include "fractalnow.h" #include class GradientBox : public QWidget { Q_OBJECT public: GradientBox(const QGradientStops &gradientStops, QWidget *parent = 0); GradientBox(const Gradient &gradient, QWidget *parent = 0); public slots: void setGradient(const Gradient &gradient); void setGradientStops(const QGradientStops &gradientStops); void openGradientDialog(); private: void initGradientBox(const QGradientStops &gradientStops); GradientLabel *gradientLabel; QGradientStops gradientStops; signals: void gradientStopsChanged(const QGradientStops &gradientStops); }; #endif fractalnow-0.8.2/gui/include/fractal_rendering_widget.h000664 001750 001750 00000003630 13175112471 023205 0ustar00mpegmpeg000000 000000 /* * fractal_rendering_widget.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal_config_widget.h * \brief Header file introducing FractalRenderingWidget class. * * \author Marc Pegon */ #ifndef __FRACTAL_RENDERING_WIDGET_H__ #define __FRACTAL_RENDERING_WIDGET_H__ #include "fractal_rendering_parameters.h" #include "color_button.h" #include "gradient_box.h" #include #include #include class FractalRenderingWidget : public QWidget { Q_OBJECT public: FractalRenderingWidget(const RenderingParameters &render); QComboBox *iterationCountComboBox; QComboBox *coloringMethodComboBox; QComboBox *addendFunctionComboBox; QSpinBox *stripeDensitySpinBox; QComboBox *interpolationMethodComboBox; QComboBox *transferFunctionComboBox; QDoubleSpinBox *colorScalingSpinBox; QDoubleSpinBox *colorOffsetSpinBox; ColorButton *spaceColorButton; GradientBox *gradientBox; public slots: void updateBoxesValues(const RenderingParameters &render); void updateBoxesEnabledValue(); void updateColorScalingSingleStep(); void editGradient(); private: void blockBoxesSignals(bool block); }; #endif fractalnow-0.8.2/examples/rendering_files/render03c.render000664 001750 001750 00000000132 13175112471 023546 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING CURVATURE LINEAR CUBE 7.5E-2 0.5 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/lib/src/fractal_formula.c000664 001750 001750 00000004366 13175115345 020465 0ustar00mpegmpeg000000 000000 /* * fractal_formula.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "fractal_formula.h" #include "error.h" #include "misc.h" #include const char *fractalFormulaStr[] = { (const char *)"mandelbrot", (const char *)"mandelbrotp", (const char *)"julia", (const char *)"juliap", (const char *)"burningship", (const char *)"juliaburningship", (const char *)"mandelbar", (const char *)"juliabar", (const char *)"rudy" }; const char *fractalFormulaDescStr[] = { (const char *)"Mandelbrot (z^2+c)", (const char *)"Multibrot (z^p+c))", (const char *)"Julia (z^2+c)", (const char *)"Multi Julia (z^p+c)", (const char *)"Burning ship ((|Re(z)|+|Im(z)|)^p+c)", (const char *)"Julia B.ship ((|Re(z)|+|Im(z)|)^p+c)", (const char *)"Mandelbar (conjugate(z)^p+c)", (const char *)"Juliabar (conjugate(z)^p+c)", (const char *)"Rudy (z^p + c*z + d)" }; const uint_fast32_t nbFractalFormulas = sizeof(fractalFormulaStr) / sizeof(const char *); int GetFractalFormula(FractalFormula *fractalFormula, const char *str) { int res = 0; size_t len = strlen(str); if (len > 255) { FractalNow_werror("Unknown fractal formula \'%s\'.\n", str); } char FFStr[256]; strcpy(FFStr, str); toLowerCase(FFStr); uint_fast32_t i; for (i = 0; i < nbFractalFormulas; ++i) { if (strcmp(FFStr, fractalFormulaStr[i]) == 0) { *fractalFormula = (FractalFormula)i; break; } } if (i == nbFractalFormulas) { FractalNow_werror("Unknown fractal formula \'%s\'.\n", str); } end: return res; } fractalnow-0.8.2/doc/gradient_file_syntax.txt000664 001750 001750 00000002544 13175112471 021324 0ustar00mpegmpeg000000 000000 Gradient file syntax: GRADIENT_FILE_FORMAT BYTES_PER_COMPONENT Pos1 Color1 ... PosN ColorN Text characters can be upper-case or lower-case. Arguments separators can be tabs, blank spaces, carriage return. GRADIENT_FILE_FORMAT should be G073, which is the format described in this document. Other format values (of older versions) may still be supported though. BYTES_PER_COMPONENT specifies the number of bytes per component used for colors. It can be : - 1 for RGB8 (8 bits per component) - 2 for RGB16 (16 bits per component) POSi : position of COLORi in gradient (between 0 and 1). First position must be 0, and last position must be 1. Positions must be strictly increasing. COLORi : colors composing gradient. Gradient must be made of at least 2 colors. Colors must be specified as hexadecimal numbers. Red, green, and blue are respectively the 1st, 2nd and 3rd component. Some RGB8 color examples : - 0x0 for black - 0xFF for blue - 0xFF00 for green - 0xFF0000 for red - 0xFFFFFF for white Some RGB16 color examples : - 0x0 for black - 0xFFFF for blue - 0xFFFF0000 for green - 0xFFFF00000000 for red - 0xFFFFFFFFFFFF for white In order for the gradient not to be discontinuous, the first and last color should be the same, for example 0x0 0xFFFFFF 0x0 for a black and white continuous gradient. Acceptable floating numbers are for example : 2.567 4.146E-5 8.26e2 fractalnow-0.8.2/command-line/src/help.c000664 001750 001750 00000007214 13175112471 020041 0ustar00mpegmpeg000000 000000 /* * help.c -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "help.h" #include "fractalnow.h" #include #include #include void DisplayHelp() { printf("fractalnow v%s - Generate fractal pictures (raw \ PPM format).\n\n\ Usage : fractalnow -h\n\ or\n\ fractalnow [OPTIONS] -c [-x |-y ] -o \ \n\ or\n\ fractalnow [OPTIONS] -f -r [-x \ |-y ] -o \n\ \n\ OPTIONS:\n" #ifdef DEBUG " -d Debug mode.\n" #endif " -j Specify number of threads \ (%"PRIuFAST32" by default).\n\ -g Specify gradient file, overriding \ gradient from configuration/rendering file.\n\ -x Specify output image width.\n\ -y Specify output image height.\n\ -l Specify float type:\n\ single Single precision.\n\ double Double precision.\n" #ifdef _ENABLE_LDOUBLE_FLOATS " ldouble Long double \ precision.\n" #endif #ifdef _ENABLE_MP_FLOATS " mp Multiple \ precision.\n\ -L Specify precision for Multiple \ Precision (MP) floats (%"PRId64" by default).\n" #endif " -a Specify anti-aliasing method:\n\ none By default.\n\ blur Gaussian blur.\n\ oversampling\n\ adaptive Smart oversampling.\ \n\ -s Specify size for anti-aliasing:\n\ Radius for blur (values in \ [2.5, 4] are generally good).\n\ Scale factor for oversampling ([3\ , 5] is good for a high quality image).\n\ Scale factor for adaptive (\ integers between 3-5 are good for a high quality image).\n\ -p Threshold for adaptive \ anti-aliasing (%G by default).\n\ -i Maximum size of quadrilaterals for \ linear interpolation.\n\ %"PRIuFAST32" by default, which is \ good for no visible loss of quality.\n\ 1 means no interpolation (all \ pixels are computed).\n\ -t Dissimilarity threshold for quad \ interpolation.\n\ %G by default, which is \ good for no visible loss of quality.\n\ A quadrilateral that shows too \ dissimilar values at its corners will be computed, \ as opposed to interpolated.\n", FractalNow_VersionNumber(), DEFAULT_NB_THREADS, #ifdef _ENABLE_MP_FLOATS DEFAULT_MP_PRECISION, #endif DEFAULT_ADAPTIVE_AAM_THRESHOLD, DEFAULT_QUAD_INTERPOLATION_SIZE, DEFAULT_COLOR_DISSIMILARITY_THRESHOLD); } fractalnow-0.8.2/examples/config_files/config01.config000664 001750 001750 00000000210 13175112471 022642 0ustar00mpegmpeg000000 000000 c075 mandelbrot -0.7 0 3 3 1000 250 1 0x0 iterationcount smooth identity 0.025 0 0 0xff 0.25 0xffffff 0.5 0xffff00 0.75 0xff0000 1 0xff fractalnow-0.8.2/doc/000775 001750 001750 00000000000 13175112471 014354 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/generate_samples.sh000775 001750 001750 00000015704 13175115345 017476 0ustar00mpegmpeg000000 000000 #!/bin/bash # # generate_samples.sh -- part of FractalNow # # Copyright (c) 2012 Marc Pegon # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # 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. # QUIET=0; VERBOSE=0; DRY_RUN=0; DEBUG=0; EXAMPLES_DIR="examples" FRACTAL_DIR="${EXAMPLES_DIR}/fractal_files" RENDER_DIR="${EXAMPLES_DIR}/rendering_files" CONFIG_DIR="${EXAMPLES_DIR}/config_files" FRACTAL_SUFFIX=".fractal" RENDER_SUFFIX=".render" CONFIG_SUFFIX=".config" IMGS_DIR="imgs" FRACTAL_FILE_PREFIX="fractal" RENDER_FILE_PREFIX="render" EXE="fractalnow" usage(){ cat< : Specify full path to fractalnow executable -f : Specify fractal files directory (default: '${FRACTAL_DIR}') -r : Specify rendering files directory (default: '${RENDER_DIR}') -c : Specify configuration files directory (default: '${CONFIG_DIR}') -o : Specify output directory for image files (default: '${IMGS_DIR}') FRACTALNOW OPTIONS (see fractalnow help) : -d -q -v -x -y -l -L (if enabled) -a -s -j EOF } function error { echo $1 >> /dev/stderr; if [ ! -z $2 ]; then exit $2; else exit 1; fi; } while getopts ":hc:e:f:r:o:qvdnx:y:a:s:j:l:L:" opt; do case "$opt" in 'h') usage; exit 1; ;; 'c') CONFIG_DIR="$OPTARG"; ;; 'e') EXE="$OPTARG"; ;; 'f') FRACTAL_DIR="$OPTARG"; ;; 'r') RENDER_DIR="$OPTARG"; ;; 'o') IMGS_DIR="$OPTARG"; ;; 'q') QUIET=1; ;; 'v') VERBOSE=1; ;; 'd') DEBUG=1; ;; 'n') DRY_RUN=1; ;; 'x') if eval [ "$OPTARG" -eq "$OPTARG" 2>/dev/null ]; then WIDTH=`eval echo "$OPTARG"`; else error 'Width is not a number.'; fi; ;; 'y') if eval [ "$OPTARG" -eq "$OPTARG" 2>/dev/null ]; then HEIGHT=`eval echo "$OPTARG"`; else error 'Height is not a number.'; fi; ;; 'l') FLOATTYPE="$OPTARG"; ;; 'L') MPFLOATPRECISION="$OPTARG"; ;; 'a') AAM="$OPTARG"; ;; 's') if eval [ "$OPTARG" -eq "$OPTARG" 2>/dev/null ]; then AAM_SIZE=`eval echo "$OPTARG"`; else error 'AAM_Size is not a number.'; fi; ;; 'j') if eval [ "$OPTARG" -eq "$OPTARG" 2>/dev/null ]; then NB_THREADS=`eval echo "$OPTARG"`; else error 'Number of threads is not a number.'; fi; ;; *) echo "Invalid option '$OPTARG'." >&2; usage; exit 1; ;; esac; done; shift $(($OPTIND - 1)) if [ $# -ne 0 ]; then echo "Unknown arguments remaining on command line."; usage; exit 1; fi; if [ -z "${WIDTH}" -a -z "${HEIGHT}" ]; then echo "At least width or height should be specified."; usage; exit 1; fi; `${EXE} -h &>/dev/null` if [ $? -ne 0 ]; then echo "Could not find '${EXE}' executable." exit 1; fi; if [ ${DRY_RUN} -eq 0 ]; then function cmd { echo "$@"; eval "$@"; } else function cmd { echo "$@"; } fi; # Make sure that FRACTAL_DIR exists and is a directory. if [ ! -e "${FRACTAL_DIR}" ]; then error "'${FRACTAL_DIR}' doesn't exist."; elif [ ! -d "${FRACTAL_DIR}" ]; then error "'${FRACTAL_DIR}' is not a directory."; fi; # Make sure that RENDER_DIR is a directory. if [ ! -e "${RENDER_DIR}" ]; then error "'${RENDER_DIR}' doesn't exist."; elif [ ! -d "${RENDER_DIR}" ]; then error "'${RENDER_DIR}' is not a directory."; fi; # Check whether IMGS_DIR exists or not if [ -e "${IMGS_DIR}" ]; then # IMGS_DIR already exists, make sure it is a directory. if [ ! -d "${IMGS_DIR}" ]; then error "'${IMGS_DIR}' is not a directory."; fi; else # IMGS_DIR doesn't exist, create it. cmd mkdir -p "\"${IMGS_DIR}\""; fi; #Set fractalnow flags if [ ${VERBOSE} -eq 1 ]; then FLAGS="$FLAGS -v"; fi; if [ ${QUIET} -eq 1 ]; then FLAGS="$FLAGS -q"; fi; if [ ! -z ${NB_THREADS} ]; then FLAGS="$FLAGS -j ${NB_THREADS}"; fi; if [ ! -z ${WIDTH} ]; then FLAGS="$FLAGS -x ${WIDTH}"; IMG_SUFFIX="${IMG_SUFFIX}_x${WIDTH}"; fi; if [ ! -z ${HEIGHT} ]; then FLAGS="$FLAGS -y ${HEIGHT}"; IMG_SUFFIX="${IMG_SUFFIX}_y${HEIGHT}"; fi; if [ ! -z ${FLOATTYPE} ]; then FLAGS="$FLAGS -l ${FLOATTYPE}"; IMG_SUFFIX="${IMG_SUFFIX}_l${FLOATTYPE}"; fi if [ ! -z ${MPFLOATPRECISION} ]; then FLAGS="$FLAGS -L ${MPFLOATPRECISION}"; IMG_SUFFIX="${IMG_SUFFIX}_L${MPFLOATPRECISION}"; fi if [ ! -z ${AAM} ]; then FLAGS="$FLAGS -a ${AAM}"; IMG_SUFFIX="${IMG_SUFFIX}_a${AAM}"; fi; if [ ! -z ${AAM_SIZE} ]; then FLAGS="$FLAGS -s ${AAM_SIZE}"; IMG_SUFFIX="${IMG_SUFFIX}_s${AAM_SIZE}"; fi; IMG_SUFFIX="${IMG_SUFFIX}.ppm"; fractal_files=`eval ls \"${FRACTAL_DIR}\" --quoting-style=c -1 | grep ^\""${FRACTAL_FILE_PREFIX}.*${FRACTAL_SUFFIX}"\"$ | sort`; IFS=$'\n'; for i in ${fractal_files} ; do fractal_file=`eval echo -e "${i}"`; fractal_file_basename=`basename "${fractal_file}" "${FRACTAL_SUFFIX}"`; fractal_file_suffix=`eval echo \"${fractal_file_basename}\" | sed "s/.*${FRACTAL_FILE_PREFIX}\(.*\)/\1/"` current_render_prefix="${RENDER_FILE_PREFIX}${fractal_file_suffix}" render_files=`eval ls \"${RENDER_DIR}\" --quoting-style=c | grep ^\""${current_render_prefix}.*${RENDER_SUFFIX}" | sort`; for j in ${render_files} ; do render_file=`eval echo -e "$j"`; render_file_basename=`basename "${render_file}" "${RENDER_SUFFIX}"`; cmd \"${EXE}\" -f \"${FRACTAL_DIR}/${fractal_file}\" -r \"${RENDER_DIR}/${render_file}\" -o \"${IMGS_DIR}/${fractal_file_basename}_${render_file_basename}${IMG_SUFFIX}\" ${FLAGS}; if [ $? -ne 0 ]; then error "Error occured when running executable. Interrupting." fi; echo; done; done; config_files=`eval ls \"${CONFIG_DIR}\" --quoting-style=c -1 | grep ^\""${CONFIG_FILE_PREFIX}.*${CONFIG_SUFFIX}"\"$ | sort`; for i in ${config_files} ; do config_file=`eval echo -e "${i}"`; config_file_basename=`basename "${config_file}" "${CONFIG_SUFFIX}"`; cmd \"${EXE}\" -c \"${CONFIG_DIR}/${config_file}\" -o \"${IMGS_DIR}/${config_file_basename}${IMG_SUFFIX}\" ${FLAGS}; if [ $? -ne 0 ]; then error "Error occured when running executable. Interrupting." fi; echo; done; fractalnow-0.8.2/lib/include/complex_wrapper.h000664 001750 001750 00000002235 13175112471 021362 0ustar00mpegmpeg000000 000000 /* * complex_wrapper.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file complex_wrapper.h * \brief Header file for wrapper for complex numbers. * * Either builtin or standard C99. * * \author Marc Pegon */ #ifndef __COMPLEX_WRAPPER_H__ #define __COMPLEX_WRAPPER_H__ #ifdef _USE_BUILTIN_COMPLEX #include "builtin_complex.h" #else #include "c99_complex_wrapper.h" #endif #endif fractalnow-0.8.2/examples/fractal_files/fractal03.fractal000664 001750 001750 00000000055 13175112471 023340 0ustar00mpegmpeg000000 000000 F075 JULIA 0.5 0.25 0.0 0.0 2.5 2.5 1E30 100 fractalnow-0.8.2/lib/src/fractal_iteration_count.c000664 001750 001750 00000003533 13175115345 022221 0ustar00mpegmpeg000000 000000 /* * fractal_iteration_count.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "fractal.h" #include "fractal_iteration_count.h" #include "error.h" #include "misc.h" #include const char *iterationCountStr[] = { (const char *)"discrete", (const char *)"continuous", (const char *)"smooth" }; const char *iterationCountDescStr[] = { (const char *)"Discrete iteration", (const char *)"Continuous iteration", (const char *)"Smooth iteration" }; const uint_fast32_t nbIterationCounts = sizeof(iterationCountStr) / sizeof(const char *); int GetIterationCount(IterationCount *iterationCount, const char *str) { int res = 0; int len = strlen(str); if (len > 255) { FractalNow_werror("Unknown iteration count \'%s\'.\n", str); } char ICStr[256]; strcpy(ICStr, str); toLowerCase(ICStr); uint_fast32_t i; for (i = 0; i < nbIterationCounts; ++i) { if (strcmp(ICStr, iterationCountStr[i]) == 0) { *(iterationCount) = (IterationCount)i; break; } } if (i == nbIterationCounts) { FractalNow_werror("Unknown iteration count \'%s\'.\n", str); } end: return res; } fractalnow-0.8.2/gui/include/gradient_dialog.h000664 001750 001750 00000002751 13175112471 021310 0ustar00mpegmpeg000000 000000 /* * gradient_dialog.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file gradient_dialog.h * \brief Header file introducing ColorButton class. * * \author Marc Pegon */ #ifndef _GRADIENT_DIALOG__H__ #define _GRADIENT_DIALOG__H__ #include "gradient_editor.h" #include #include class GradientDialog : public QDialog { Q_OBJECT public: GradientDialog(const QGradientStops &gradientStops, QWidget *parent = 0, Qt::WindowFlags f = 0); const QGradientStops ¤tGradientStops() const; private: GradientEditor *gradientEditor; QGradientStops gradientStops; private slots: void initGradientEditor(); void onGradientStopsChanged(const QGradientStops &gradientStops); }; #endif fractalnow-0.8.2/lib/Makefile.configure000664 001750 001750 00000004244 13175115345 020004 0ustar00mpegmpeg000000 000000 SRCDIR = src INCLUDEDIR= include OBJDIR = objs BINDIR = bin TARGET = ${BINDIR}/${TARGET_NAME} DEPENDENCY_FILE=${OBJDIR}/makefile.dep CC = gcc AR = ar ARFLAGS = -r -c -s CFLAGS = -std=c99 -pedantic -Wall -Wextra -D${SPINLOCK_DEFINE} ifdef BUILTIN_COMPLEX_DEFINE CFLAGS += -D${BUILTIN_COMPLEX_DEFINE} endif ifdef MP_FLOATS_DEFINE CFLAGS += -D${MP_FLOATS_DEFINE} endif ifdef LDOUBLE_FLOATS_DEFINE CFLAGS += -D${LDOUBLE_FLOATS_DEFINE} endif ifdef VERSION_NUMBER CFLAGS += -DVERSION_NUMBER=${VERSION_NUMBER} endif ifdef DEBUG CFLAGS += -O0 -g -DDEBUG else CFLAGS += -O2 -ffast-math endif CFLAGS += -I${INCLUDEDIR} OBJECTS = \ $(OBJDIR)/complex_wrapper.o \ $(OBJDIR)/float_precision.o \ $(OBJDIR)/fractal_addend_function.o \ $(OBJDIR)/fractal_cache.o \ $(OBJDIR)/fractal_coloring.o \ $(OBJDIR)/fractal_compute_engine.o \ $(OBJDIR)/fractal_config.o \ $(OBJDIR)/fractal_iteration_count.o \ $(OBJDIR)/fractal_formula.o \ $(OBJDIR)/error.o \ $(OBJDIR)/fractal_rendering_parameters.o \ $(OBJDIR)/fractal_transfer_function.o \ $(OBJDIR)/color.o \ $(OBJDIR)/file_io.o \ $(OBJDIR)/filter.o \ $(OBJDIR)/fractalnow.o \ $(OBJDIR)/fractal.o \ $(OBJDIR)/gradient.o \ $(OBJDIR)/image.o \ $(OBJDIR)/misc.o \ $(OBJDIR)/ppm.o \ $(OBJDIR)/uirectangle.o \ $(OBJDIR)/task.o \ $(OBJDIR)/thread.o all : $(OBJDIR) $(BINDIR) ${DEPENDENCY_FILE} $(TARGET) ${DEPENDENCY_FILE}: $(OBJDIR) ${SRCDIR}/*.c ${INCLUDEDIR}/*.h $(call quiet-command,for i in ${SRCDIR}/*.c; do ${CC} ${CFLAGS} -MM "$${i}"; done | sed "s/\(^.*:\)/${OBJDIR}\/\1/" > $@," BUILDING DEPENDENCY DATABASE"); -include ${DEPENDENCY_FILE} $(TARGET): $(OBJECTS) $(call quiet-command, $(AR) $(ARFLAGS) $@ $^, " AR $@") $(OBJDIR): $(call quiet-command, mkdir -p $(OBJDIR),) $(BINDIR): $(call quiet-command, mkdir -p $(BINDIR),) $(OBJDIR)/%.o:${SRCDIR}/%.c ${CC} ${CFLAGS} -c $< -o $@ clean: $(call quiet-command, rm -f ${DEPENDENCY_FILE}, " CLEAN (DEPENDENCY DATABASE)") $(call quiet-command, rm -f $(OBJECTS) , " CLEAN (OBJECTS)") distclean: clean $(call quiet-command, rm -rf $(OBJDIR), " CLEAN (OBJDIR)") $(call quiet-command, rm -rf $(BINDIR), " CLEAN (BINDIR)") fractalnow-0.8.2/gui/src/command_line.cpp000664 001750 001750 00000015551 13175112471 020322 0ustar00mpegmpeg000000 000000 /* * command_line.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "command_line.h" #include "help.h" #include #include #include int FileExists(const char *fileName) { FILE *file; int res = 0; if ((file = fopen(fileName,"r")) != NULL) { res = 1; fclose(file); } return res; } CommandLineArguments::CommandLineArguments(int argc, char *argv[]) { FractalNow_traceLevel = T_NORMAL; FractalNow_debug = 0; int help = 0; long int tmp = 0; fractalConfigFileName = NULL; fractalFileName = NULL; renderingFileName = NULL; gradientFileName = NULL; int minAntiAliasingSizeSpecified = 0; int maxAntiAliasingSizeSpecified = 0; int antiAliasingSizeIterationSpecified = 0; adaptiveAAMThreshold = DEFAULT_ADAPTIVE_AAM_THRESHOLD; colorDissimilarityThreshold = DEFAULT_COLOR_DISSIMILARITY_THRESHOLD; quadInterpolationSize = DEFAULT_QUAD_INTERPOLATION_SIZE; nbThreads = -1; floatPrecision = FP_DOUBLE; #ifdef _ENABLE_MP_FLOATS MPFloatPrecision = DEFAULT_MP_PRECISION; #endif width = 0; height = 0; int o; while ((o = getopt(argc, argv, "hvda:f:i:j:l:L:m:nM:r:x:y:t:c:g:r:p:q")) != -1) { switch (o) { case 'h': help = 1; break; case 'v': FractalNow_traceLevel = T_VERBOSE; break; case 'q': FractalNow_traceLevel = T_QUIET; break; case 'd': #ifndef DEBUG FractalNow_message(stdout, T_QUIET, "Debug unavailable: %s was not built in \ debug mode.\n", QApplication::applicationName().toStdString().c_str()); #else FractalNow_debug = 1; #endif break; case 'c': fractalConfigFileName = optarg; break; case 'f': fractalFileName = optarg; break; case 'r': renderingFileName = optarg; break; case 'g': gradientFileName = optarg; break; case 'l': if (GetFloatPrecision(&floatPrecision, optarg)) { invalid_use_error("\n"); } break; #ifdef _ENABLE_MP_FLOATS case 'L': if (sscanf(optarg, "%ld", &tmp) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (tmp < GetMinMPFloatPrecision() || tmp > GetMaxMPFloatPrecision()) { invalid_use_error("MP floats precision must be between %"PRId64" and %"PRId64".\n", GetMinMPFloatPrecision(), GetMaxMPFloatPrecision()); } else { MPFloatPrecision = tmp; } break; #endif case 'i': if (sscanf(optarg, "%ld", &tmp) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (tmp <= 0) { invalid_use_error("Quad interpolation size must be positive.\n"); } else { quadInterpolationSize = (uint_fast32_t)tmp; } break; case 'j': if (sscanf(optarg, "%d", &nbThreads) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (nbThreads <= 0) { invalid_use_error("Number of threads must be positive.\n"); } break; case 'm': if (sscanf(optarg, "%ld", &tmp) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (tmp < 2) { invalid_use_error("Minimum anti-aliasing size must be >= 2.\n"); } minAntiAliasingSize = (uint_fast32_t)tmp; minAntiAliasingSizeSpecified = 1; break; case 'n': if (sscanf(optarg, "%ld", &tmp) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (tmp < 1) { invalid_use_error("Anti-aliasing size iteration must be >= 1.\n"); } antiAliasingSizeIteration = (uint_fast32_t)tmp; antiAliasingSizeIterationSpecified = 1; break; case 'M': if (sscanf(optarg, "%ld", &tmp) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (tmp < 2) { invalid_use_error("Maximum anti-aliasing size must be >= 2.\n"); } maxAntiAliasingSize = (uint_fast32_t)tmp; maxAntiAliasingSizeSpecified = 1; break; case 'x': if (sscanf(optarg, "%ld", &tmp) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (tmp < 2) { invalid_use_error("Output image width must be >= 2.\n"); } else { width = (uint_fast32_t)tmp; } break; case 'y': if (sscanf(optarg, "%ld", &tmp) < 1) { invalid_use_error("Command-line argument \'%s\' is not a number.\n", optarg); } if (tmp < 2) { invalid_use_error("Output image height must be >= 2.\n"); } else { height = (uint_fast32_t)tmp; } break; case 'p': if (sscanf(optarg, "%lf", &adaptiveAAMThreshold) < 1) { invalid_use_error("Command-line argument \'%s\' is not a floating-point number.\n", optarg); } if (adaptiveAAMThreshold < 0.) { invalid_use_error("Adaptive anti-aliasing threshold must be >= 0.\n"); } break; case 't': if (sscanf(optarg, "%lf", &colorDissimilarityThreshold) < 1) { invalid_use_error("Command-line argument \'%s\' is not a floating-point number.\n", optarg); } if (colorDissimilarityThreshold < 0.) { invalid_use_error("Quad dissimilarity threshold must be between >= 0.\n"); } break; default: Help::Print(); exit(EXIT_FAILURE); break; } } if (argv[optind] != NULL) { invalid_use_error("Remaining argument on command line : '%s'.\n", argv[optind]); } if (help) { Help::Print(); exit(EXIT_SUCCESS); } if (!antiAliasingSizeIterationSpecified) { antiAliasingSizeIteration = DEFAULT_ANTIALIASING_SIZE_ITERATION; } if (!minAntiAliasingSizeSpecified) { minAntiAliasingSize = DEFAULT_MIN_ANTIALIASING_SIZE; } if (!maxAntiAliasingSizeSpecified) { maxAntiAliasingSize = DEFAULT_MAX_ANTIALIASING_SIZE; } if (minAntiAliasingSize > maxAntiAliasingSize) { invalid_use_error("Maximum anti-aliasing size must be greater than minimum anti-aliasing size.\n"); } if (fractalConfigFileName != NULL && !FileExists(fractalConfigFileName)) { FractalNow_existence_error(fractalConfigFileName); } if (fractalFileName != NULL && !FileExists(fractalFileName)) { FractalNow_existence_error(fractalFileName); } if (renderingFileName != NULL && !FileExists(renderingFileName)) { FractalNow_existence_error(renderingFileName); } if (gradientFileName != NULL && !FileExists(gradientFileName)) { FractalNow_existence_error(gradientFileName); } } fractalnow-0.8.2/examples/fractal_files/fractal04.fractal000664 001750 001750 00000000055 13175112471 023341 0ustar00mpegmpeg000000 000000 F075 JULIA 0.5 0.25 0.0 0.0 2.5 2.5 1E20 100 fractalnow-0.8.2/lib/include/c99_complex_wrapper.h000664 001750 001750 00000010566 13175112471 022054 0ustar00mpegmpeg000000 000000 /* * c99_complex_wrapper.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file c99_complex_wrapper.h * \brief Header file for wrapper for standard C99 complex numbers. * \author Marc Pegon */ #ifndef __C99_COMPLEX_WRAPPER_H__ #define __C99_COMPLEX_WRAPPER_H__ #include #include #ifdef __cplusplus extern "C" { #endif #ifndef complex #define complex _Complex #endif /** * \fn float cnormf(float complex a) * \brief Compute norm of float complex * * Norm is defined as re*re+im*im. * * \param a Complex number. * \return Norm of a. */ float cnormf(float complex a); /** * \fn double cnorm(double complex a) * \brief Compute norm of double complex. * * Norm is defined as re*re+im*im. * * \param a Complex number. * \return Norm of a. */ double cnorm(double complex a); /** * \fn long double cnorml(long double complex a) * \brief Compute norm of long double complex. * * Norm is defined as re*re+im*im. * * \param a Complex number. * \return Norm of a. */ long double cnorml(long double complex a); /** * \fn float complex cipowf(float complex a, uint_fast32_t b) * \brief Compute integral power of float complex a. * * \param a Complex number. * \param b Integral power of return value. * \return a to the power b. */ float complex cipowf(float complex a, uint_fast32_t b); double complex cipow(double complex a, uint_fast32_t b); long double complex cipowl(long double complex a, uint_fast32_t b); int cisintegerf(float complex a); int cisinteger(double complex a); int cisintegerl(long double complex a); /**************************float**************************/ typedef float complex Complex_f; #define cbuild_f(re, im) ((re)+I*(im)) #define ceq_f(a, b) ((a)==(b)) #define creal_f(a) crealf(a) #define cimag_f(a) cimagf(a) #define conj_f(a) conjf(a) #define cnorm_f(a) cnormf(a) #define cabs_f(a) cabsf(a) #define cadd_f(a,b) ((a)+(b)) #define csub_f(a,b) ((a)-(b)) #define csqr_f(a) ((a)*(a)) #define cmul_f(a,b) ((a)*(b)) #define cdiv_f(a,b) ((a)/(b)) #define carg_f(a) cargf(a) #define cexp_f(a) cexpf(a) #define clog_f(a) clogf(a) #define cipow_f(a,b) cipowf(a,b) #define cpow_f(a,b) cpowf(a,b) #define cisinteger_f(a) cisintegerf(a) /*********************************************************/ /**************************double*************************/ typedef double complex Complex_; #define cbuild_(re, im) ((re)+I*(im)) #define ceq_(a, b) ((a)==(b)) #define creal_(a) creal(a) #define cimag_(a) cimag(a) #define conj_(a) conj(a) #define cnorm_(a) cnorm(a) #define cabs_(a) cabs(a) #define cadd_(a,b) ((a)+(b)) #define csub_(a,b) ((a)-(b)) #define csqr_(a) ((a)*(a)) #define cmul_(a,b) ((a)*(b)) #define cdiv_(a,b) ((a)/(b)) #define carg_(a) carg(a) #define cexp_(a) cexp(a) #define clog_(a) clog(a) #define cipow_(a,b) cipow(a,b) #define cpow_(a,b) cpow(a,b) #define cisinteger_(a) cisinteger(a) /*********************************************************/ /***********************long double***********************/ typedef long double complex Complex_l; #define cbuild_l(re, im) ((re)+I*(im)) #define ceq_l(a, b) ((a)==(b)) #define creal_l(a) creall(a) #define cimag_l(a) cimagl(a) #define conj_l(a) conjl(a) #define cnorm_l(a) cnorml(a) #define cabs_l(a) cabsl(a) #define cadd_l(a,b) ((a)+(b)) #define csub_l(a,b) ((a)-(b)) #define csqr_l(a) ((a)*(a)) #define cmul_l(a,b) ((a)*(b)) #define cdiv_l(a,b) ((a)/(b)) #define carg_l(a) cargl(a) #define cexp_l(a) cexpl(a) #define clog_l(a) clogl(a) #define cipow_l(a,b) cipowl(a,b) #define cpow_l(a,b) cpowl(a,b) #define cisinteger_l(a) cisintegerl(a) /*********************************************************/ #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/gui/src/fractal_config_widget.cpp000664 001750 001750 00000017000 13175112471 022170 0ustar00mpegmpeg000000 000000 /* * fractal_config_widget.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "main.h" #include "fractal_config_widget.h" #include #include #include FractalConfigWidget::FractalConfigWidget(const Fractal &fractal) : QWidget() { fractalFormulaComboBox = new QComboBox; for (uint_fast32_t i = 0; i < nbFractalFormulas; ++i) { fractalFormulaComboBox->addItem(fractalFormulaDescStr[i]); } pParamReSpinBox = new MPFRSpinBox; pParamReSpinBox->setDecimals(DEFAULT_DECIMALS_NUMBER); pParamReSpinBox->setRange(0, 100); pParamReSpinBox->setAccelerated(true); pParamImSpinBox = new MPFRSpinBox; pParamImSpinBox->setDecimals(DEFAULT_DECIMALS_NUMBER); pParamImSpinBox->setRange(0, 100); pParamImSpinBox->setAccelerated(true); cParamReSpinBox = new MPFRSpinBox; cParamReSpinBox->setDecimals(DEFAULT_DECIMALS_NUMBER); cParamReSpinBox->setRange(-100, 100); cParamReSpinBox->setAccelerated(true); cParamImSpinBox = new MPFRSpinBox; cParamImSpinBox->setDecimals(DEFAULT_DECIMALS_NUMBER); cParamImSpinBox->setRange(-100, 100); cParamImSpinBox->setAccelerated(true); centerXSpinBox = new MPFRSpinBox; centerXSpinBox->setRange(-100, 100); centerXSpinBox->setAccelerated(true); centerXSpinBox->setNotation(MPFRSpinBox::ScientificNotation); centerYSpinBox = new MPFRSpinBox; centerYSpinBox->setRange(-100, 100); centerYSpinBox->setAccelerated(true); centerYSpinBox->setNotation(MPFRSpinBox::ScientificNotation); spanXSpinBox = new MPFRSpinBox; spanXSpinBox->setRange(0, std::numeric_limits::max()); spanXSpinBox->setAccelerated(true); spanXSpinBox->setNotation(MPFRSpinBox::ScientificNotation); bailoutRadiusSpinBox = new QDoubleSpinBox; bailoutRadiusSpinBox->setDecimals(0); bailoutRadiusSpinBox->setRange(1, std::numeric_limits::max()); bailoutRadiusSpinBox->setAccelerated(true); maxIterationsSpinBox = new QSpinBox; maxIterationsSpinBox->setRange(1, std::numeric_limits::max()); maxIterationsSpinBox->setAccelerated(true); QFormLayout *formLayout = new QFormLayout; formLayout->addRow(tr("Fractal formula:"), fractalFormulaComboBox); formLayout->addRow(tr("p (Re):"), pParamReSpinBox); formLayout->addRow(tr("p (Im):"), pParamImSpinBox); formLayout->addRow(tr("c (Re):"), cParamReSpinBox); formLayout->addRow(tr("c (Im):"), cParamImSpinBox); formLayout->addRow(tr("Center X:"), centerXSpinBox); formLayout->addRow(tr("Center Y:"), centerYSpinBox); formLayout->addRow(tr("Span X:"), spanXSpinBox); formLayout->addRow(tr("Bailout radius:"), bailoutRadiusSpinBox); formLayout->addRow(tr("Max iterations:"), maxIterationsSpinBox); this->setLayout(formLayout); updateBoxesValues(fractal); updateSpaceBoxesSingleSteps(); updateCParamReSingleStep(); updateCParamImSingleStep(); updateBoxesEnabledValue(); connect(spanXSpinBox, SIGNAL(valueChanged(const mpfr_t *)), this, SLOT(updateSpaceBoxesSingleSteps())); connect(cParamReSpinBox, SIGNAL(valueChanged(const mpfr_t *)), this, SLOT(updateCParamReSingleStep())); connect(cParamImSpinBox, SIGNAL(valueChanged(const mpfr_t *)), this, SLOT(updateCParamImSingleStep())); connect(fractalFormulaComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateBoxesEnabledValue())); } void FractalConfigWidget::blockBoxesSignals(bool block) { fractalFormulaComboBox->blockSignals(block); pParamReSpinBox->blockSignals(block); pParamImSpinBox->blockSignals(block); cParamReSpinBox->blockSignals(block); cParamImSpinBox->blockSignals(block); centerXSpinBox->blockSignals(block); centerYSpinBox->blockSignals(block); spanXSpinBox->blockSignals(block); bailoutRadiusSpinBox->blockSignals(block); maxIterationsSpinBox->blockSignals(block); } void FractalConfigWidget::updateBoxesValues(const Fractal &fractal) { blockBoxesSignals(true); fractalFormulaComboBox->setCurrentIndex((int)fractal.fractalFormula); pParamReSpinBox->setValue(&mpc_realref(fractal.p)); pParamImSpinBox->setValue(&mpc_imagref(fractal.p)); cParamReSpinBox->setValue(&mpc_realref(fractal.c)); cParamImSpinBox->setValue(&mpc_imagref(fractal.c)); centerXSpinBox->setValue(&fractal.centerX); centerYSpinBox->setValue(&fractal.centerY); spanXSpinBox->setValue(&fractal.spanX); bailoutRadiusSpinBox->setValue(fractal.escapeRadius); maxIterationsSpinBox->setValue(fractal.maxIter); updateBoxesEnabledValue(); updateSpaceBoxesSingleSteps(); updateCParamReSingleStep(); updateCParamImSingleStep(); blockBoxesSignals(false); } void FractalConfigWidget::updateSpaceBoxesSingleSteps() { const mpfr_t * spanX = spanXSpinBox->value(); if (mpfr_cmp_ui(*spanX, 0) <= 0) { centerXSpinBox->setSingleStep(MIN_SINGLE_STEP); centerYSpinBox->setSingleStep(MIN_SINGLE_STEP); spanXSpinBox->setSingleStep(MIN_SINGLE_STEP); } else { mpfr_t step; mpfr_init(step); mpfr_div_ui(step, *spanX, 5, MPFR_RNDN); centerXSpinBox->setSingleStep(&step); centerYSpinBox->setSingleStep(&step); mpfr_mul_d(step, *spanX, 0.3, MPFR_RNDN); spanXSpinBox->setSingleStep(&step); mpfr_clear(step); } } void FractalConfigWidget::updateCParamReSingleStep() { const mpfr_t *cParamRe = cParamReSpinBox->value(); if (mpfr_cmp_ui(*cParamRe, 0) <= 0) { cParamReSpinBox->setSingleStep(MIN_SINGLE_STEP); } else { mpfr_t step; mpfr_init(step); mpfr_div_ui(step, *cParamRe, 5, MPFR_RNDN); cParamReSpinBox->setSingleStep(&step); mpfr_clear(step); } } void FractalConfigWidget::updateCParamImSingleStep() { const mpfr_t *cParamIm = cParamImSpinBox->value(); if (mpfr_cmp_ui(*cParamIm, 0) <= 0) { cParamImSpinBox->setSingleStep(MIN_SINGLE_STEP); } else { mpfr_t step; mpfr_init(step); mpfr_div_ui(step, *cParamIm, 5, MPFR_RNDN); cParamImSpinBox->setSingleStep(&step); mpfr_clear(step); } } void FractalConfigWidget::updateBoxesEnabledValue() { FractalFormula formula = (FractalFormula)fractalFormulaComboBox->currentIndex(); switch (formula) { case FRAC_MANDELBROT: pParamReSpinBox->setEnabled(false); pParamImSpinBox->setEnabled(false); cParamReSpinBox->setEnabled(false); cParamImSpinBox->setEnabled(false); break; case FRAC_MULTIBROT: case FRAC_BURNINGSHIP: case FRAC_MANDELBAR: pParamReSpinBox->setEnabled(true); pParamImSpinBox->setEnabled(true); cParamReSpinBox->setEnabled(false); cParamImSpinBox->setEnabled(false); break; case FRAC_JULIA: pParamReSpinBox->setEnabled(false); pParamImSpinBox->setEnabled(false); cParamReSpinBox->setEnabled(true); cParamImSpinBox->setEnabled(true); break; case FRAC_MULTIJULIA: case FRAC_JULIABURNINGSHIP: case FRAC_JULIABAR: case FRAC_RUDY: pParamReSpinBox->setEnabled(true); pParamImSpinBox->setEnabled(true); cParamReSpinBox->setEnabled(true); cParamImSpinBox->setEnabled(true); break; default: pParamReSpinBox->setEnabled(true); pParamImSpinBox->setEnabled(true); cParamReSpinBox->setEnabled(true); cParamImSpinBox->setEnabled(true); break; } } fractalnow-0.8.2/examples/config_files/config04.config000664 001750 001750 00000000311 13175112471 022647 0ustar00mpegmpeg000000 000000 c075 mandelbrot -0.74364421961 0.13182604688 6.82671004784689E-07 6.82671004784689E-07 16 5000 1 0x0 iterationcount smooth squareroot 0.028 0 0 0x39a0 0.25 0xffffff 0.5 0xfffe43 0.75 0xbf0800 1 0x39a0 fractalnow-0.8.2/lib/include/filter.h000664 001750 001750 00000022042 13175112471 017436 0ustar00mpegmpeg000000 000000 /* * filter.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file filter.h * \brief Header file related to image filters. * \author Marc Pegon * * Convolution filters are used to apply transformations on image, such * as gaussian blur. */ #ifndef __FILTER_H__ #define __FILTER_H__ #include "image.h" #include "thread.h" #include #ifdef __cplusplus extern "C" { #endif /** * \struct Filter * \brief Structure to represent an image filter. * * A filter is typically a matrix (kernel) with a center of application. */ /** * \typedef Filter * \brief Convenient typedef for struct Filter. */ typedef struct Filter { uint_fast32_t sx; /*!< Number of columns.*/ uint_fast32_t sy; /*!< Number of rows.*/ uint_fast32_t cx; /*!< X coordinate of filter's center.*/ uint_fast32_t cy; /*!< Y coordinate of filter's center.*/ double *data; /*!< Filter data (the elements of the matrix).*/ } Filter; /** * \fn void InitFilter(Filter *filter, uint_fast32_t sx, uint_fast32_t sy, uint_fast32_t cx, uint_fast32_t cy, double *data) * \brief Initialize filter. * * Data will be owned by filter, and freed when the filter is freed, * so it must have been dynamically allocated. * * \param filter Pointer to the filter structure to initialize. * \param sx Number of columns. * \param sy Number of lines. * \param cx X coordinate of filter's center. * \param cy Y coordinate of filter's center. * \param data Filter data (NOT copied, and will be freed when the filter is freed). */ void InitFilter(Filter *filter, uint_fast32_t sx, uint_fast32_t sy, uint_fast32_t cx, uint_fast32_t cy, double *data); /** * \fn void InitFilter2(Filter *filter, uint_fast32_t sx, uint_fast32_t sy, double *data) * \brief Initialize filter without specifying center. * * The center is automatically computed : ((sx-1)/2, (sy-1)/2).\n * Data will be owned by filter, and freed when the filter is freed, * so it must have been dynamically allocated. * * \param filter Pointer to the filter structure to initialize. * \param sx Number of columns. * \param sy Number of lines. * \param data Filter data (NOT copied, and will be freed when the filter is freed). */ void InitFilter2(Filter *filter, uint_fast32_t sx, uint_fast32_t sy, double *data); /** * \fn Filter CopyFilter(const Filter *filter) * \brief Copy filter. * * \param filter Pointer to filter to copy. * \return Copy of filter. */ Filter CopyFilter(const Filter *filter); /** * \fn void CreateHorizontalGaussianFilter(Filter *filter, double sigma) * \brief Create a horizontal gaussian filter given sigma. * * sigma must be strictly positive (exit with error otherwise). * * \param filter Pointer to the filter structure to initialize. * \param sigma See Wikipedia (or others) for that. */ void CreateHorizontalGaussianFilter(Filter *filter, double sigma); /** * \fn void CreateHorizontalGaussianFilter2(Filter *filter, double radius) * \brief Create a horizontal gaussian filter given its radius. * * radius must be strictly positive (exit with error otherwise). * * \param filter Pointer to the filter structure to initialize. * \param radius Blur radius. */ void CreateHorizontalGaussianFilter2(Filter *filter, double radius); /** * \fn void CreateVerticalGaussianFilter(Filter *filter, double sigma) * \brief Create a vertical gaussian filter given sigma. * * sigma must be strictly positive (exit with error otherwise). * * \param filter Pointer to the filter structure to initialize. * \param sigma See Wikipedia (or others) for that. */ void CreateVerticalGaussianFilter(Filter *filter, double sigma); /** * \fn void CreateVerticalGaussianFilter2(Filter *filter, double radius) * \brief Create a vertical gaussian filter given its radius. * * radius must be strictly positive (exit with error otherwise). * * \param filter Pointer to the filter structure to initialize. * \param radius Blur radius. */ void CreateVerticalGaussianFilter2(Filter *filter, double radius); /** * \fn void CreateGaussianFilter(Filter *filter, double sigma) * \brief Create a square gaussian filter given sigma. * * sigma must be strictly positive (exit with error otherwise).\n * Note that it is actually more efficient (computationally speaking) * to apply a horizontal and then vertical gaussian filter (or vice * versa), with the same sigma, than to apply a square gaussian * filter. * * \param filter Pointer to the filter structure to initialize. * \param sigma See Wikipedia (or others) for that. */ void CreateGaussianFilter(Filter *filter, double sigma); /** * \fn void CreateGaussianFilter2(Filter *filter, double radius) * \brief Create a square gaussian filter given its radius. * * radius must be strictly positive (exit with error otherwise).\n * Note that it is actually more efficient (computationally speaking) * to apply a horizontal and then vertical gaussian filter (or vice * versa), with the same radius, than to apply a square gaussian * filter. * * \param filter Pointer to the filter structure to initialize. * \param radius Blur Radius */ void CreateGaussianFilter2(Filter *filter, double radius); /** * \fn double GetFilterValueUnsafe(const Filter *filter, uint_fast32_t x, uint_fast32_t y) * \brief Get some particular value of filter. * * Get value of filter at row x, column y.\n * Warning: function does not check whether (x,y) is within * range or not (undefined behaviour otherwise). * * \param filter Filter we want to get some particular value. * \param x Row of the filter value. * \param y Column of the filter value. * \return Value at position (x,y) of filter. */ double GetFilterValueUnsafe(const Filter *filter, uint_fast32_t x, uint_fast32_t y); /** * \fn void MultiplyFilterByScalar(Filter *filter, double scalar) * \brief Multiply whole filter by scalar. * * Multiply each filter's value by a scalar. * * \param filter Filter to be modified. * \param scalar Scalar to multiply the filter by. */ void MultiplyFilterByScalar(Filter *filter, double scalar); /** * \fn int NormalizeFilter(Filter *filter) * \brief Normalize filter. * * Warning : some filters cannot be normalized (if the sum of * its values is equal to 0).\n * If the filter cannot be normalized, it will be left unchanged. * * \param filter Filter to normalize. * \return 1 if it cannot be normalized, 0 otherwise. */ int NormalizeFilter(Filter *filter); /** * \fn Color ApplyFilterOnSinglePixel(const Image *src, uint_fast32_t x, uint_fast32_t y, const Filter *filter) * \brief Apply a filter on a single pixel of an image. * * It is safe to pass (x,y) outside image.\n * Pixels outside of the image will be duplicates of the pixels * at the sides of it. * * \param src Image we apply the filter on. * \param x X coordinate of the pixel of the image we apply the filter on. * \param y Y coordinate of the pixel of the image we apply the filter on. * \param filter Filter we apply on the image. * @return Result of the application of the filter on pixel (x,y) of the image. */ Color ApplyFilterOnSinglePixel(const Image *src, uint_fast32_t x, uint_fast32_t y, const Filter *filter); /** * \fn void ApplyFilter(Image *dst, const Image *src, const Filter *filter, Threads *threads) * \brief Apply filter on image. * * This function does not work in place. * * \param dst Destination image. * \param src Source image. * \param filter Filter to apply. * \param threads Threads to be used for task. */ void ApplyFilter(Image *dst, const Image *src, const Filter *filter, Threads *threads); /** * \fn Task *CreateApplyFilterTask(Image *dst, const Image *src, const Filter *filter, uint_fast32_t nbThreads) * \brief Create task applying a filte on an image. * * Create task adapted to nbThreads threads, and return * immediately.\n * When launching task, Threads structure should provide * enough threads (at least number specified here). * * \param dst Destination image. * \param src Source image. * \param filter Filter to apply. * \param nbThreads Number of threads that action will need to be launched. * \return Corresponding newly-allocated task. */ Task *CreateApplyFilterTask(Image *dst, const Image *src, const Filter *filter, uint_fast32_t nbThreads); /** * \fn void FreeFilter(Filter filter) * \brief Free filter. * * \param filter Filter to be freed. */ void FreeFilter(Filter filter); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/gradient_files/gradient05b.gradient000664 001750 001750 00000000276 13175112471 024234 0ustar00mpegmpeg000000 000000 G073 2 0 0x0 0.1 0x060020000E00 0.2 0x2700A7004A00 0.3 0x6000F600A800 0.4 0xAB00FA00EA00 0.5 0xDF00E600FE00 0.6 0xF900B400EF00 0.7 0xF9006A00B400 0.8 0xBB002F005800 0.9 0x270008001100 1 0x0 fractalnow-0.8.2/gui/icons/icon96x96.png000664 001750 001750 00000031541 13175112471 017676 0ustar00mpegmpeg000000 000000 PNG  IHDR``w8gAMA asRGB cHRMz&u0`:pQ<bKGDC pHYs   vpAg``x2AIDATxͽi$u7ګ@@E Dd-k,qb&<0{8!KCmˣP)dNEwiH6/YN̬z RdDE~/+s?5spo嶬|^0f񣿳x4V  \WϋcHӣ-_K׫VrX #I ;; Si)_3VӧS&ޞuscx>c g _UgEnJ7Ba8Л]_Zv1``pN^_n,_h'/!I>1L.Lrw}iy\y#>Z_2/I^wr2gsc=}D\N ;M:JIYjҴɂM&DV :phN<=|g2Q$p1|nT)K\z pff^M:/*/+cܫ ]\ey- wx9 a($異];DLfli өɿ* {^- a42 j[X(;Nzؾ0B]d07}dbE$kZuL&7t[u\<4 ɍ*X9a-_?U}ϢFv29XQh4dN ˟A%ٔ|cLF HSr˽j$P9%ROe΍c66~pbOJQ\6ʕqLDA !9L"e UKeWOh!oى"a2HhY Z \hVF58Q$*;j /^XZP + hHlߍ➺_ G#{TZѢ_v10pxUeUǕӴ.!%Ȋ/?*U|Lj/۲ <m1*(0. EVZ.~'I$: RxG =2|/RḜ(/^R &SlLL8uYJE>á}h$ҟ.j&:#R_vqɡkjԆʑ" 'acDMp]gU?km#p# Egw:} ( ek`(ϟ$]zɥ[?XVA|lV@ P>ShQB%Ҳgi$P<,5cȍy a`6/D@lZ2{T*ƈ F](M>~YFz n3ahX_wDc0,U*X8SI߇F#sc~zxbVKTp'b<;x 1x"w/&p!An˵,iyY̫L*sdvG2JM&! kkuG`ZAlk6]2G.P:Mı՚l$O^^"_UtvN:ib8"8Pj'ӕ 軖O0*`/sHvy"9?8809޲)tZ7 dHsE)aks. I1[=>oo܈[_b#$շ7hXfm-gPii-yN ɵ2}e$U JGQ$9\ nFahh\G3n %I$"xsyz]<76<66$Ncztc/OvBi*>~`luO6!?5}@ąr;8=y^kxi OSN$f\xn@m3#$IH'8xluH/tVB*N A GB]\8[!4&7bT|UoeqnH vJ[Q3F/$_KorӼǥO>l=: 'dx~gF-wK j=>A}.iL 6# o'MmfZTu /P#f$1WiZn TUiFżVN"e01} 0#M=s?׹ q|Qss{|?F<ʀO2Og$(83Mc S`0`x?Ug'm'>7~h' ػ$nVb8!(k~"=vf000 ͦxRb@4By:Tb$ gٽSp{eG{ٗ8#"D8dz=5\Y޷w8uUj0~L_fxLfˍ~_Wm<]^32Sqֺ;_/p/{O0OƯzp)7>ulqx(hT$7P.օ]V+pˊ\aUkeU$Z\ ͦd*F}8"$x0&Ƙ,`b$=~Pi v'C$s"~OuÖy~o?FdkoŘ*PTlkЩjfSf}ՏGi݌aT/wM^fz2Obh`&< 4[ ̀}`G[~e'|);v^m~ˋW?I'HjDT*AїUzXe_qL*V"R:DZpxJo$pNZ-!a p Bc|& b\*Rbzg? O3M&gM|z+㇯~ f3c®Fd%0.__km.R=l&.J6 &L<X kl1{sL/{:ɳ>mClyx?%:v5pamK|._ܕwI:7N7+6/ ɜڢX8Bˢ x ZM2^*Zqlw1өX_Rٜ)@.>/|$ͫm?ix~z皜|y'-0c{/Kw~]-~nC$I c\n- ԆrY r^Qf' .+r63llIS1+6Bx?i? x|ʗΥ56wXǴ_F̳wKyq'eڽ@2nLjɤ(f `& pd}oDzz֌ Ib癯<bd1ng3лn`: v1k{XkS;;d܌G^ HJop|>_w^kυz=t]Q%e۫U *PK0uu'´Z.{,Lq7k59O邓ķcGyi>bKSGK/:'ICj)=\ůfpU~Dԝ$IpoMi9Z>|(D1BQ/yk&_v{d&K 0YN1.7 `̳6q?lre 7{3{jw%+Ĺ&iD- h/ڢR/7BSI;&fҌju*oc1Ø|%zu`Cm^Wٹ1&|}z܄1#nM#Pۼ$ 0F͙:_.TF*S+RA4!j%T*s|b h y.sn5@R)]o#:[K_}OOk\4Nm<ͨ Gtir4yJӑNcZgln^$f a̘/?4wŷPo_I2ȼ"Ag %O)q_Syysak(9:r8L=rX Suo0L ÔZMGZMټXo<~Ҕei_c#GmZ}ke8t*9QAZwb|~Z4QRxޔ5 7e*Zbl"yg1i˃8{/5U<9#m)}e+|ྟ<`ͤO>9jO-QAR. 9w ?V;bTk]֜f|$Ęu0&ε640`P羛-」_20x}l48u'˯+:v{S.mwY;y=9?w5'U|F7 djfF: 45! (wCULK1@K]xU0F_ڈwf<=.ϲuT7ȓ-➻ILB$IB90ϗzȗMuphb̌dժ*R6N` GT™qu_zM@%lN/'t8ԧ}ڱE  Kz Rn(% =OժbW@Z`:!e8Hv}duAE~]|F<:}Õ>ӯL|? CQH,RRr2Ha(逋>\lQmF\ӾdyǗx&Iw]ѓ`}6>ígf|m;!lS:Iu4z^wthjv /JjB| (j5q]dsJ1bؼE&m)?vvrOOS(&Ș`}Tt@)_x}$~3 Hsp钬&p,F^:p#,^q)O@!+Kq3pޟ[oyT>?c-y='HkfNIe֑ͦ[uj[ỵ&eC,-?<)NV ,^_Oʸ߉dֱ8g?ˢwMak9Co +TKw6s;ns٫8v7֘[^h(gɖ[}Ӓ^׾آV{ܼ(Vbb sR2<{߿hiɛ ZqA WJ 0#zLG Owdo$q?x8 +H0'h;b]"Nc<c9[[g'ʨ_y 1-JV$O)5l{ѬӍMnlW]נQ>^M';~u>Gfw1~TVޭACgJH|#/kg۔C[- ޘ;F%NFj_@,*P5l#b&$TQT1rncT<=7U_bxHnQZlUwtoy&ǯ'Ʒ /M;r)l4E|LrqYߜ˧PA&ߖg<.7\Y<;ҙ=;+ ddBvW* ע_p A֤'KYxq&Ǜ~bN}Y2?gwypp4? 9dd2$ #N͟ѨhVcw_Os.7pL>yZ7|?0H2j<}A ]Y.XEP"6MUb|}A 7Щ(ѐs]͔1Vi4 ^2& zyiZ7 T8vwy'|~wx``5:_q]uFSe.<|p=ѱixf67~Ƀ&[t2X1<:JUmhÁ;n#\76R*ٱye0(fM:8 k<6Ya7x/ k<.I7oqC6n<0_? LF8×yh':wא~iu1gAqx(]|4RMá [&I"*gը $&.F[t" ilFxY21^2ǫ_*pcׁ.qˆlMg?׾4] 6 h\4RG<1]p0&2Cճ궼˹crsݪ-/[5U&u)],:E1#_=׀ 62T>ad b ~35>iZ ͊ZU1ucdb2R]],jqY xKX*z&'ڗ`k1ZŜ .w #uۓfS(xc8vuxLqc WN|wͱㆍ+`lufZJ-T;ج۱pBcSU`hKe/̧"|Iai/UG],DoJWLmM`NEcg2;1 hm]~9o&~]3n]q`eU:O$NA:r#vGMnn.FReզ ]ƐLҟڬ\ tEbē$^lSscTwY^੝Sa#~ }}4:t1z6[ld|,=h@z+EC2_(,eN_&-/rrL 9h.Qޑ}iV*LAIty2)1MAZ# nmS\Ώ[CsV8wg0m6uhtw-\zthES\N,]?14SNc2k+l.*T^0 i6NGWsKӑ*cZ>O 1({UpMf&өRSdͻe0Z]:JaY./aUOd#ˇ^KKg<E,_qeoy?/B~ҥ6?`0PMtdMP"Rt\LR2+#s$K˅"=@U*LiU;'DEYLi"Uu&9]PiQg }|5s^yy/$)MO/:SvIjGy1t;keYl/GӲbt\M%@6+<4%H{⤮|Ks9ʴȲ+ojmN'_*Y|w :e_-`/sq/tgV_fSˋ^B/8FUTH_J_(ZSV5RPP<^ g=j5ͩ$;qn:5F'Jw6*(^`)"Z8LTee.)[IEŘUպػ<ͦG!d5ˈoYJUJ 0~;Y\ΙVsVLm*Tٲ~mU\W8 bUs'U$\<(,Ees9LI4O^|z LQPX_v}·ӑ15>ʰ=ЋV.mv5Qjc-&./>T-j\f- [^UvyQ|TbeO1|9vNDW;ToMWeܣ|lYp[YVy弴^0"sr٠kArlF>t\Z-/ªyQn'hӶc4⓾A*kR$˙2G&Qvժ1uug3U,߯ ?їze&먭X[yú$\|UϷLUonjǼT6MxUKrx(Ei*x)^_A =YJpb \SڐnwwEGZ^U){_ 0Ύժl2EaXT^,Be5t9~nKLX^.S9<酗#r*\M[OX KJbyBb;ٌd-SV~PMSjz9˿|eW̧ՒW;Gr|ݲk4#Ύ)VG%vpkx윴W$]2g@l {_5?%tEXtdate:create2012-05-27T10:48:29+02:00+b%tEXtdate:modify2012-05-27T10:48:29+02:00qIENDB`fractalnow-0.8.2/gui/include/help.h000664 001750 001750 00000002362 13175112471 017122 0ustar00mpegmpeg000000 000000 /* * help.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file help.h * \brief Header file introducing Help class. * * \author Marc Pegon */ #ifndef __HELP_H__ #define __HELP_H__ #include "fractalnow.h" #include //! To print help on the command line. class Help { public: //! Print program help. static void Print(); }; #define invalid_use_error(...) \ FractalNow_message(stderr, T_QUIET, __VA_ARGS__);\ Help::Print(); \ exit(EXIT_FAILURE) #endif fractalnow-0.8.2/examples/gradient_files/gradient05a.gradient000664 001750 001750 00000000210 13175112471 024217 0ustar00mpegmpeg000000 000000 G073 1 0 0x0 0.1 0x06200E 0.2 0x27A74A 0.3 0x60F6A8 0.4 0xABFAEA 0.5 0xDFE6FE 0.6 0xF9B4EF 0.7 0xF96AB4 0.8 0xBB2F58 0.9 0x270811 1 0x0 fractalnow-0.8.2/lib/000775 001750 001750 00000000000 13175146244 014362 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/COPYING.LESSER000664 001750 001750 00000016743 13175112471 015651 0ustar00mpegmpeg000000 000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. fractalnow-0.8.2/lib/include/builtin_complex.h000664 001750 001750 00000004563 13175115345 021361 0ustar00mpegmpeg000000 000000 /* * builtin_complex.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file builtin_complex.h * \brief Header file for builtin complex numbers. * \author Marc Pegon */ #ifndef __BUILTIN_COMPLEX_H__ #define __BUILTIN_COMPLEX_H__ #include #include #ifdef __cplusplus extern "C" { #endif #ifdef BUILD_COMPLEX #undef BUILD_COMPLEX #endif #define BUILD_COMPLEX(type, suffix) \ typedef struct Complex_##suffix {\ type re;\ type im;\ } Complex_##suffix;\ \ Complex_##suffix cbuild_##suffix(type re, type im);\ int ceq_##suffix(Complex_##suffix a, Complex_##suffix b);\ type creal_##suffix(Complex_##suffix a);\ type cimag_##suffix(Complex_##suffix a);\ Complex_##suffix conj_##suffix(Complex_##suffix a);\ type cnorm_##suffix(Complex_##suffix a);\ type cabs_##suffix(Complex_##suffix a);\ Complex_##suffix cadd_##suffix(Complex_##suffix a, Complex_##suffix b);\ Complex_##suffix csub_##suffix(Complex_##suffix a, Complex_##suffix b);\ Complex_##suffix csqr_##suffix(Complex_##suffix a);\ Complex_##suffix cmul_##suffix(Complex_##suffix a, Complex_##suffix b);\ Complex_##suffix cdiv_##suffix(Complex_##suffix a, Complex_##suffix b);\ type carg_##suffix(Complex_##suffix a);\ Complex_##suffix cexp_##suffix(Complex_##suffix a);\ Complex_##suffix clog_##suffix(Complex_##suffix a);\ Complex_##suffix cipow_##suffix(Complex_##suffix x, uint_fast32_t y);\ Complex_##suffix cpow_##suffix(Complex_##suffix a, Complex_##suffix b);\ int cisinteger_##suffix(Complex_##suffix x); BUILD_COMPLEX(float, f) BUILD_COMPLEX(double, ) BUILD_COMPLEX(long double, l) #undef BUILD_COMPLEX #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/gui/src/shade_widget.cpp000664 001750 001750 00000010134 13175112471 020314 0ustar00mpegmpeg000000 000000 /**************************************************************************** ** ** This file is based on some files of the demonstration applications of the ** Qt Toolkit. ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Modified to be used as a part of FractalNow: ** Copyright (c) 2012 Marc Pegon ** ** This file can be distributed and/or modified under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation. ** You should have received a copy of the GNU General Public License ** along with this file; if not, write to the Free Software Foundation, Inc., ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ** ****************************************************************************/ #include "shade_widget.h" ShadeWidget::ShadeWidget(ShadeType type, QWidget *parent) : QWidget(parent), m_shade_type(type), m_alpha_gradient(QLinearGradient()) { // Checkers background if (m_shade_type == ARGBShade) { QPixmap pm(20, 20); QPainter pmp(&pm); pmp.fillRect(0, 0, 10, 10, Qt::lightGray); pmp.fillRect(10, 10, 10, 10, Qt::lightGray); pmp.fillRect(0, 10, 10, 10, Qt::darkGray); pmp.fillRect(10, 0, 10, 10, Qt::darkGray); pmp.end(); QPalette pal = palette(); pal.setBrush(backgroundRole(), QBrush(pm)); setAutoFillBackground(true); setPalette(pal); } else { setAttribute(Qt::WA_NoBackground); } QPolygonF points; points << QPointF(0, sizeHint().height()) << QPointF(sizeHint().width(), 0); m_hoverPoints = new HoverPoints(this, HoverPoints::CircleShape); // m_hoverPoints->setConnectionType(HoverPoints::LineConnection); m_hoverPoints->setPoints(points); m_hoverPoints->setPointLock(0, HoverPoints::LockToLeft); m_hoverPoints->setPointLock(1, HoverPoints::LockToRight); m_hoverPoints->setSortType(HoverPoints::XSort); m_hoverPoints->setConnectionType(HoverPoints::LineConnection); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); connect(m_hoverPoints, SIGNAL(pointsChanged(QPolygonF)), this, SIGNAL(colorsChanged())); } QPolygonF ShadeWidget::points() const { return m_hoverPoints->points(); } unsigned int ShadeWidget::colorAt(int x) { generateShade(); QPolygonF pts = m_hoverPoints->points(); for (int i=1; i < pts.size(); ++i) { if (pts.at(i-1).x() <= x && pts.at(i).x() >= x) { QLineF l(pts.at(i-1), pts.at(i)); l.setLength(l.length() * ((x - l.x1()) / l.dx())); return m_shade.pixel(qRound(qMin(l.x2(), (qreal(m_shade.width() - 1)))), qRound(qMin(l.y2(), qreal(m_shade.height() - 1)))); } } return 0; } void ShadeWidget::setGradientStops(const QGradientStops &stops) { if (m_shade_type == ARGBShade) { m_alpha_gradient = QLinearGradient(0, 0, width(), 0); for (int i=0; i * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file export_fractal_image_dialog.h * \brief Header file introducing ExportFractalImageDialog class. * * \author Marc Pegon */ #ifndef __EXPORT_FRACTAL_IMAGE_DIALOG_H__ #define __EXPORT_FRACTAL_IMAGE_DIALOG_H__ #include #include #include #include #include #include #include #include "fractalnow.h" class ExportFractalImageDialog : public QDialog { Q_OBJECT public: ExportFractalImageDialog(const FractalConfig &config, uint_fast32_t nbThreads, QString imageDir = QString(), QWidget *parent = 0, Qt::WindowFlags f = 0); void resetFractalConfig(const FractalConfig &config); void setFloatPrecision(FloatPrecision floatPrecision); QString exportedFile(); ~ExportFractalImageDialog(); private: void TaskProgressBar(Task *task, QString labelText, QString cancelButtonText); enum AntiAliasingMethod { AAM_NONE = 0, AAM_GAUSSIANBLUR, AAM_OVERSAMPLING, AAM_ADAPTIVE }; AntiAliasingMethod getAntiAliasingMethod() const; QString m_exportedFile; QString imageDir; FractalConfig config; Fractal &fractal; RenderingParameters &render; Threads *threads; FloatPrecision floatPrecision; QComboBox *colorDepthBox; QLineEdit *outputFileEdit; QRadioButton *noAAMButton; QRadioButton *gaussianBlurAAMButton; QDoubleSpinBox *blurRadiusBox; QRadioButton *adaptiveAAMButton; QSpinBox *adaptiveSizeBox; QRadioButton *oversamplingAAMButton; QDoubleSpinBox *oversamplingSizeBox; QSpinBox *imageWidthBox; QSpinBox *imageHeightBox; QDialogButtonBox *dialogButtonBox; QPushButton *exportButton; QPushButton *cancelButton; private slots: void onAAMNoneToggled(bool); void onAAMBlurToggled(bool); void onAAMAdaptiveToggled(bool); void onAAMOversamplingToggled(bool); void exportImage(); }; #endif fractalnow-0.8.2/examples/config_files/config22.config000664 001750 001750 00000000343 13175112471 022654 0ustar00mpegmpeg000000 000000 c075 burningship 2 0 -1.93690187628336 -0.00325452399171512 0.0159734941326134 0.0159734941326134 1000 250 1 0x0 iterationcount smooth identity 0.0155125997538578 0.87 0 0x39a0 0.25 0xffffff 0.5 0xfffe43 0.75 0xbf0800 1 0x39a0 fractalnow-0.8.2/examples/gradient_files/gradient03b.gradient000664 001750 001750 00000000061 13175112471 024222 0ustar00mpegmpeg000000 000000 G073 2 0 0xFFFFFFFFFFFF 0.5 0x0 1 0xFFFFFFFFFFFF fractalnow-0.8.2/examples/config_files/config11.config000664 001750 001750 00000000321 13175112471 022646 0ustar00mpegmpeg000000 000000 c075 rudy 3 0 -0.7198 0.9111 0.820152733159133 -0.668118265464959 0.000130552070959935 0.000130552070959935 100000 10000 1 0x0 averagecoloring triangleinequality linear log 6.3 0 0 0xffffff 0.5 0x0 1 0xffffff fractalnow-0.8.2/examples/gradient_files/gradient03a.gradient000664 001750 001750 00000000045 13175112471 024223 0ustar00mpegmpeg000000 000000 G073 1 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/ChangeLog000664 001750 001750 00000001111 13175135346 015361 0ustar00mpegmpeg000000 000000 0.8.2 2017-10-28 Marc Pegon * Switched to Qt5. 0.8.1 2012-07-11 Marc Pegon * Made gradient offset spin box circular. * Improved icons. * Updated file formats documentation. * Minor bug fixes. * Source cleaning. 0.8.0 2012-05-13 Marc Pegon * Added support for Multiple Precision floats using MPFR and MPC libraries. * Added possibility to change float type (float, double, long double, mpfr_t) at runtime. 0.7.5 2012-04-12 Marc Pegon * Initial release. fractalnow-0.8.2/lib/src/fractal_cache.c000664 001750 001750 00000067372 13175115345 020071 0ustar00mpegmpeg000000 000000 /* * fractal_cache.c -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "float_precision.h" #include "fractal_cache.h" #include "fractal.h" #include "macro_build_floats.h" #include "misc.h" #include "uirectangle.h" #include "thread.h" #define HandleRequests(max_counter) \ if (counter == max_counter) {\ HandlePauseRequest(threadArgHeader);\ cancelRequested =\ CancelTaskRequested(threadArgHeader);\ counter = 0;\ } else {\ ++counter;\ } inline void FreeCacheEntry(CacheEntry entry) { switch (entry.floatPrecision) { case FP_SINGLE: clearF(FP_SINGLE, entry.x.val_FP_SINGLE); clearF(FP_SINGLE, entry.y.val_FP_SINGLE); break; case FP_DOUBLE: clearF(FP_DOUBLE, entry.x.val_FP_DOUBLE); clearF(FP_DOUBLE, entry.y.val_FP_DOUBLE); break; #ifdef _ENABLE_LDOUBLE_FLOATS case FP_LDOUBLE: clearF(FP_LDOUBLE, entry.x.val_FP_LDOUBLE); clearF(FP_LDOUBLE, entry.y.val_FP_LDOUBLE); break; #endif #ifdef _ENABLE_MP_FLOATS case FP_MP: clearF(FP_MP, entry.x.val_FP_MP); clearF(FP_MP, entry.y.val_FP_MP); break; #endif default: FractalNow_error("Unknown float precision.\n"); break; } } int CreateFractalCache(FractalCache *cache, uint_least64_t size) { int res = 0; cache->firstUse = 1; cache->fractal = (Fractal *)safeMalloc("fractal", sizeof(Fractal)); cache->render = (RenderingParameters *)safeMalloc("rendering parameters", sizeof(RenderingParameters)); cache->currentState = 0; cache->nbInitialized = 0; cache->size = size; cache->entry = (CacheEntry *)malloc(size*sizeof(CacheEntry)); if (cache->entry == NULL) { res = 1; cache->size = 0; } cache->currentIndex = 0; cache->arrayWidth = 0; cache->arrayHeight = 0; cache->array = NULL; safePThreadSpinInit(&cache->arrayMutex, SPIN_INIT_ATTR); safePThreadSpinInit(&cache->entryMutex, SPIN_INIT_ATTR); return res; } int ResizeCacheThreadSafe(FractalCache *cache, uint_least64_t size) { if (size == cache->size) { return 0; } int res = 1; safePThreadSpinLock(&cache->entryMutex); if (size < cache->size) { for (uint_fast32_t i = size; i < cache->size; ++i) { FreeCacheEntry(cache->entry[i]); } } void *newEntry = (CacheEntry *)realloc(cache->entry, size*sizeof(CacheEntry)); if (size == 0 || newEntry != NULL) { res = 0; cache->entry = newEntry; cache->size = size; if (cache->nbInitialized > size) { cache->nbInitialized = size; } if (cache->currentIndex >= size) { cache->currentIndex = 0; } } safePThreadSpinUnlock(&cache->entryMutex); return res; } inline void AddToCache(FractalCache *cache, CacheEntry entry) { if (cache->size == 0) { return; } if (cache->nbInitialized < cache->size) { ++cache->nbInitialized; } else { FreeCacheEntry(cache->entry[cache->currentIndex]); } cache->entry[cache->currentIndex++] = entry; if (cache->currentIndex >= cache->size) { cache->currentIndex = 0; } } void AddToCacheThreadSafe(FractalCache *cache, CacheEntry entry) { safePThreadSpinLock(&cache->entryMutex); AddToCache(cache, entry); safePThreadSpinUnlock(&cache->entryMutex); } static inline CacheEntry GetCacheEntry(FractalCache *cache, uint_least64_t index) { return cache->entry[index]; } static inline CacheEntry GetCacheEntryThreadSafe(FractalCache *cache, uint_least64_t index) { CacheEntry res; safePThreadSpinLock(&cache->entryMutex); res = GetCacheEntry(cache, index); safePThreadSpinUnlock(&cache->entryMutex); return res; } typedef struct ClearCacheArrayArguments { uint_fast32_t threadId; FractalCache *cache; uint_fast32_t nbRectangles; UIRectangle *rectangles; } ClearCacheArrayArguments; void FreeClearCacheArrayArguments(void *arg) { ClearCacheArrayArguments *c_arg = (ClearCacheArrayArguments *)arg; if (c_arg->threadId == 0) { free(c_arg->rectangles); } } void *ClearCacheArrayThreadRoutine(void *arg) { ThreadArgHeader *threadArgHeader = GetThreadArgHeader(arg); ClearCacheArrayArguments *c_arg = (ClearCacheArrayArguments *)GetThreadArgBody(arg); FractalCache *cache = c_arg->cache; uint_fast32_t nbRectangles = c_arg->nbRectangles; UIRectangle *currentRect; uint_fast32_t rectHeight; ArrayValue *aVal; uint_fast32_t counter = 0; for (uint_fast32_t i = 0; i < nbRectangles; ++i) { currentRect = &c_arg->rectangles[i]; rectHeight = currentRect->y2+1-currentRect->y1; for (uint_fast32_t j = currentRect->y1; j <= currentRect->y2; ++j) { SetThreadProgress(threadArgHeader, 100 * (i*rectHeight+j) / (nbRectangles*rectHeight)); /* Handling pause & cancelation requests after each * scanline should be good enough since operations * on each pixel are trivial */ for (uint_fast32_t k = currentRect->x1; k <= currentRect->x2; ++k) { if (counter == 256) { HandlePauseRequest(threadArgHeader); counter = 0; } else { ++counter; } aVal = &cache->array[j][k]; aVal->state = cache->currentState; aVal->totalWeight = 0; aVal->r = 0; aVal->g = 0; aVal->b = 0; } } } SetThreadProgress(threadArgHeader, 100); int canceled = CancelTaskRequested(threadArgHeader); return (canceled ? PTHREAD_CANCELED : NULL); } char clearCacheArrayMessage[] = "Clearing cache array"; Task *CreateClearCacheArrayTask(FractalCache *cache, uint_fast32_t width, uint_fast32_t height, uint_fast32_t nbThreads) { if (width == 0 || height == 0) { return DoNothingTask(); } uint_fast32_t nbPixels = width*height; uint_fast32_t nbThreadsNeeded = nbThreads; uint_fast32_t rectanglesPerThread = DEFAULT_RECTANGLES_PER_THREAD; if (nbPixels <= nbThreadsNeeded) { nbThreadsNeeded = nbPixels; rectanglesPerThread = 1; } else if (nbPixels < nbThreadsNeeded*rectanglesPerThread) { rectanglesPerThread = nbPixels / nbThreadsNeeded; } uint_fast32_t nbRectangles = nbThreadsNeeded*rectanglesPerThread; UIRectangle *rectangle; rectangle = (UIRectangle *)safeMalloc("rectangles", nbRectangles * sizeof(UIRectangle)); InitUIRectangle(&rectangle[0], 0, 0, width-1, height-1); if (CutUIRectangleInN(rectangle[0], nbRectangles, rectangle)) { FractalNow_error("Could not cut rectangle ((%"PRIuFAST32",%"PRIuFAST32"),\ (%"PRIuFAST32",%"PRIuFAST32") in %"PRIuFAST32" parts.\n", rectangle[0].x1, rectangle[0].y1, rectangle[0].x2, rectangle[0].y2, nbRectangles); } ClearCacheArrayArguments *arg; arg = (ClearCacheArrayArguments *)safeMalloc("arguments", nbThreadsNeeded * sizeof(ClearCacheArrayArguments)); for (uint_fast32_t i = 0; i < nbThreadsNeeded; ++i) { arg[i].threadId = i; arg[i].cache = cache; arg[i].nbRectangles = rectanglesPerThread; arg[i].rectangles = &rectangle[i*rectanglesPerThread]; } Task *task = CreateTask(clearCacheArrayMessage, nbThreadsNeeded, arg, sizeof(ClearCacheArrayArguments), ClearCacheArrayThreadRoutine, FreeClearCacheArrayArguments); free(arg); return task; } void ClearCacheArray(FractalCache *cache, Threads *threads) { Task *task = CreateClearCacheArrayTask(cache, cache->arrayWidth, cache->arrayHeight, threads->N); int unused = ExecuteTaskBlocking(task, threads); UNUSED(unused); } static inline Color ColorFromValue(double value, const RenderingParameters *render) { Color res; if (value < 0) { res = render->spaceColor; } else { value = render->transferFunctionPtr(value)*render->realMultiplier+ render->realOffset; res = GetGradientColor(&render->gradient, (uint_fast64_t)(value)); } return res; } static inline ArrayValue aux_PutIntoArray(FractalCache *cache, uint_fast32_t x, uint_fast32_t y, double r, double g, double b, double weight) { ArrayValue *aVal = &cache->array[y][x]; if (aVal->state != cache->currentState) { aVal->r = 0; aVal->g = 0; aVal->b = 0; aVal->totalWeight = 0; aVal->state = cache->currentState; } aVal->r += r; aVal->g += g; aVal->b += b; aVal->totalWeight += weight; return *aVal; } static inline ArrayValue PutIntoArray(FractalCache *cache, const RenderingParameters *render, uint_fast32_t x, uint_fast32_t y, double value, double weight) { Color color = ColorFromValue(value, render); double r = color.r * weight; double g = color.g * weight; double b = color.b * weight; return aux_PutIntoArray(cache, x, y, r, g, b, weight); } static inline ArrayValue PutIntoArrayThreadSafe(FractalCache *cache, const RenderingParameters *render, uint_fast32_t x, uint_fast32_t y, double value, double weight) { Color color = ColorFromValue(value, render); double r = color.r * weight; double g = color.g * weight; double b = color.b * weight; safePThreadSpinLock(&cache->arrayMutex); ArrayValue res = aux_PutIntoArray(cache, x, y, r, g, b, weight); safePThreadSpinUnlock(&cache->arrayMutex); return res; } inline ArrayValue GetArrayValue(FractalCache *cache, uint_fast32_t x, uint_fast32_t y) { return cache->array[y][x]; } static inline ArrayValue GetArrayValueThreadSafe(FractalCache *cache, uint_fast32_t x, uint_fast32_t y) { safePThreadSpinLock(&cache->arrayMutex); ArrayValue aVal = GetArrayValue(cache, x, y); safePThreadSpinUnlock(&cache->arrayMutex); return aVal; } inline int isArrayValueValid(ArrayValue aVal, FractalCache *cache) { return (aVal.state == cache->currentState && aVal.totalWeight > DEFAULT_CACHE_WEIGHT_THRESHOLD); } inline Color GetColorFromAVal(ArrayValue aVal, const RenderingParameters *render) { Color res; res.bytesPerComponent = render->bytesPerComponent; res.r = aVal.r / aVal.totalWeight; res.g = aVal.g / aVal.totalWeight; res.b = aVal.b / aVal.totalWeight; return res; } static inline int isInsideArray(FLOATTYPE(FP_LDOUBLE) x, FLOATTYPE(FP_LDOUBLE) y, uint_fast32_t width, uint_fast32_t height) { return (x >= 0 && x <= width-1 && y <= height-1 && y >= 0); } typedef struct ResizeCacheArrayArguments { FractalCache *cache; uint_fast32_t width; uint_fast32_t height; } ResizeCacheArrayArguments; void FreeResizeCacheArrayArguments(void *arg) { UNUSED(arg); } void ResizeCacheArray(FractalCache *cache, uint_fast32_t width, uint_fast32_t height) { for (uint_fast32_t i = 0; i < cache->arrayHeight; ++i) { free(cache->array[i]); } cache->array = (ArrayValue **)safeRealloc("cache array", cache->array, height*sizeof(ArrayValue *)); for (uint_fast32_t i = 0; i < height; ++i) { cache->array[i] = (ArrayValue *)safeMalloc("cache array", width*sizeof(ArrayValue)); } cache->arrayWidth = width; cache->arrayHeight = height; } void *ResizeCacheArrayThreadRoutine(void *arg) { ResizeCacheArrayArguments *c_arg = (ResizeCacheArrayArguments *)GetThreadArgBody(arg); ResizeCacheArray(c_arg->cache, c_arg->width, c_arg->height); return NULL; } char resizeCacheArrayMessage[] = "Resizing cache array"; Task *CreateResizeCacheArrayTask(FractalCache *cache, uint_fast32_t width, uint_fast32_t height) { ResizeCacheArrayArguments arg; arg.cache = cache; arg.width = width; arg.height = height; Task *task = CreateTask(resizeCacheArrayMessage, 1, &arg, sizeof(ResizeCacheArrayArguments), ResizeCacheArrayThreadRoutine, FreeResizeCacheArrayArguments); return task; } int InvalidateCacheArray(FractalCache *cache) { int res = 0; if (cache->currentState == UINT_FAST32_MAX) { cache->currentState = 0; res = 1; } else { ++cache->currentState; } return res; } typedef struct FillCacheArrayArguments { uint_fast32_t threadId; uint_least64_t begin, end; Image *image; pthread_spinlock_t *imageMutex; const Fractal *fractal; const RenderingParameters *render; FractalCache *cache; DECL_MULTI_FLOAT(spanX); DECL_MULTI_FLOAT(spanY); DECL_MULTI_FLOAT(x1); DECL_MULTI_FLOAT(y1); } FillCacheArrayArguments; void FreeFillCacheArrayArguments(void *arg) { FillCacheArrayArguments *c_arg = (FillCacheArrayArguments *)arg; if (c_arg->threadId == 0) { safePThreadSpinDestroy(c_arg->imageMutex); free((void *)c_arg->imageMutex); } CLEAR_MULTI_FLOAT(c_arg->spanX); CLEAR_MULTI_FLOAT(c_arg->spanY); CLEAR_MULTI_FLOAT(c_arg->x1); CLEAR_MULTI_FLOAT(c_arg->y1); } #define BUILD_GetImageCoordFromCacheEntry(fprec) \ static void GetImageCoordFromCacheEntry_##fprec(CacheEntry *entry,\ double *outx, double *outy,\ FLOATTYPE(fprec) x, FLOATTYPE(fprec) y,\ uint_fast32_t width, uint_fast32_t height,\ FLOATTYPE(fprec) spanX, FLOATTYPE(fprec) spanY,\ FLOATTYPE(fprec) x1, FLOATTYPE(fprec) y1)\ {\ subF(fprec, x, FLOAT_VAR(fprec,entry->x.val), x1);\ mul_uiF(fprec, x, x, width);\ divF(fprec, x, x, spanX);\ sub_dF(fprec, x, x, 0.5);\ *outx = toDoubleF(fprec, x);\ \ subF(fprec, y, FLOAT_VAR(fprec,entry->y.val), y1);\ mul_uiF(fprec, y, y, height);\ divF(fprec, y, y, spanY);\ sub_dF(fprec, y, y, 0.5);\ *outy = toDoubleF(fprec, y);\ } #undef MACRO_BUILD_FLOAT #define MACRO_BUILD_FLOAT(fprec) BUILD_GetImageCoordFromCacheEntry(fprec) MACRO_BUILD_FLOATS #define BUILD_SwitchCacheEntry(fprec)\ case fprec:\ GetImageCoordFromCacheEntry_##fprec(&entry, &x, &y,\ FLOAT_VAR(fprec,multiX), FLOAT_VAR(fprec,multiY),\ cache->arrayWidth, cache->arrayHeight,\ FLOAT_VAR(fprec,c_arg->spanX), FLOAT_VAR(fprec,c_arg->spanY),\ FLOAT_VAR(fprec,c_arg->x1), FLOAT_VAR(fprec,c_arg->y1));\ break; #undef MACRO_BUILD_FLOAT #define MACRO_BUILD_FLOAT(fprec) BUILD_SwitchCacheEntry(fprec) void *FillCacheArrayThreadRoutine(void *arg) { ThreadArgHeader *threadArgHeader = GetThreadArgHeader(arg); FillCacheArrayArguments *c_arg = (FillCacheArrayArguments *)GetThreadArgBody(arg); FractalCache *cache = c_arg->cache; const Fractal *fractal = c_arg->fractal; const RenderingParameters *render = c_arg->render; Image *image = c_arg->image; pthread_spinlock_t *imageMutex = c_arg->imageMutex; CacheEntry entry; double x = 0, y = 0; uint_least64_t nbEntries = c_arg->end-c_arg->begin+1; uint_fast32_t counter = 0; int cancelRequested = CancelTaskRequested(threadArgHeader); double dx, dy; uint_fast32_t intX, intY; double sigma = 1./3; double sigma2_x_2 = sigma*sigma*2; double weight; DECL_MULTI_FLOAT(multiX); DECL_MULTI_FLOAT(multiY); INIT_MULTI_FLOAT(multiX); INIT_MULTI_FLOAT(multiY); ASSIGN_MULTI_FLOAT(multiX, fractal->centerX); ASSIGN_MULTI_FLOAT(multiY, fractal->centerY); ArrayValue aVal; Color color; for (uint_least64_t i = c_arg->begin; i <= c_arg->end && !cancelRequested; ++i) { SetThreadProgress(threadArgHeader, 100 * (i-c_arg->begin) / nbEntries); HandleRequests(128); entry = GetCacheEntry(cache, i); switch(entry.floatPrecision) { MACRO_BUILD_FLOATS default: FractalNow_error("Unknown float precision.\n"); break; } intX = roundl(x); intY = roundl(y); dx = x - intX; dy = y - intY; if (isInsideArray(intX, intY, cache->arrayWidth, cache->arrayHeight)) { weight = exp(-(dx*dx+dy*dy)/sigma2_x_2); if (image != NULL) { safePThreadSpinLock(imageMutex); aVal = PutIntoArray(cache, render, intX, intY, entry.value, weight); color = GetColorFromAVal(aVal, render); PutPixelUnsafe(image, intX, intY, color); safePThreadSpinUnlock(imageMutex); } else { aVal = PutIntoArrayThreadSafe(cache, render, intX, intY, entry.value, weight); } } } CLEAR_MULTI_FLOAT(multiX); CLEAR_MULTI_FLOAT(multiY); SetThreadProgress(threadArgHeader, 100); int canceled = CancelTaskRequested(threadArgHeader); return (canceled ? PTHREAD_CANCELED : NULL); } char fillCacheArrayMessage[] = "Filling cache array"; Task *CreateFillCacheArrayTask(FractalCache *cache, Image *image, const Fractal *fractal, const RenderingParameters *render, uint_fast32_t nbThreads) { if (cache->size == 0 || cache->arrayWidth == 0 || cache->arrayHeight == 0 || cache->nbInitialized == 0) { return DoNothingTask(); } uint_fast32_t nbEntries = cache->nbInitialized; uint_fast32_t nbThreadsNeeded = nbThreads; if (nbEntries <= nbThreadsNeeded) { nbThreadsNeeded = nbEntries; } uint_fast32_t nbRectangles = nbThreadsNeeded; UIRectangle *rectangle; rectangle = (UIRectangle *)safeMalloc("rectangles", nbRectangles * sizeof(UIRectangle)); InitUIRectangle(&rectangle[0], 0, 0, nbEntries-1, 0); if (CutUIRectangleInN(rectangle[0], nbRectangles, rectangle)) { FractalNow_error("Could not cut rectangle ((%"PRIuFAST32",%"PRIuFAST32"),\ (%"PRIuFAST32",%"PRIuFAST32") in %"PRIuFAST32" parts.\n", rectangle[0].x1, rectangle[0].y1, rectangle[0].x2, rectangle[0].y2, nbRectangles); } pthread_spinlock_t *imageMutex; imageMutex = (pthread_spinlock_t *)safeMalloc("image mutex", sizeof(pthread_spinlock_t)); safePThreadSpinInit(imageMutex, SPIN_INIT_ATTR); FillCacheArrayArguments *arg; arg = (FillCacheArrayArguments *)safeMalloc("arguments", nbThreadsNeeded * sizeof(FillCacheArrayArguments)); for (uint_fast32_t i = 0; i < nbThreadsNeeded; ++i) { arg[i].threadId = i; arg[i].cache = cache; arg[i].image = image; arg[i].imageMutex = imageMutex; arg[i].fractal = fractal; arg[i].render = render; arg[i].begin = rectangle[i].x1; arg[i].end = rectangle[i].x2; INIT_MULTI_FLOAT(arg[i].spanX); INIT_MULTI_FLOAT(arg[i].spanY); INIT_MULTI_FLOAT(arg[i].x1); INIT_MULTI_FLOAT(arg[i].y1); ASSIGN_MULTI_FLOAT(arg[i].spanX, fractal->spanX); ASSIGN_MULTI_FLOAT(arg[i].spanY, fractal->spanY); ASSIGN_MULTI_FLOAT(arg[i].x1, fractal->x1); ASSIGN_MULTI_FLOAT(arg[i].y1, fractal->y1); } Task *task = CreateTask(fillCacheArrayMessage, nbThreadsNeeded, arg, sizeof(FillCacheArrayArguments), FillCacheArrayThreadRoutine, FreeFillCacheArrayArguments); free(arg); free(rectangle); return task; } void FillCacheArray(FractalCache *cache, Image *image, const Fractal *fractal, const RenderingParameters *render, Threads *threads) { Task *task = CreateFillCacheArrayTask(cache, image, fractal, render, threads->N); int unused = ExecuteTaskBlocking(task, threads); UNUSED(unused); } typedef struct FillImageFromCacheArrayArguments { uint_fast32_t threadId; FractalCache *cache; Image *image; const RenderingParameters *render; uint_fast32_t nbRectangles; UIRectangle *rectangles; } FillImageFromCacheArrayArguments; void FreeFillImageFromCacheArrayArguments(void *arg) { FillImageFromCacheArrayArguments *c_arg = (FillImageFromCacheArrayArguments *)arg; if (c_arg->threadId == 0) { free(c_arg->rectangles); } } void *FillImageFromCacheArrayThreadRoutine(void *arg) { ThreadArgHeader *threadArgHeader = GetThreadArgHeader(arg); FillImageFromCacheArrayArguments *c_arg = (FillImageFromCacheArrayArguments *)GetThreadArgBody(arg); FractalCache *cache = c_arg->cache; Image *dst = c_arg->image; const RenderingParameters *render = c_arg->render; uint_fast32_t nbRectangles = c_arg->nbRectangles; UIRectangle *currentRect; uint_fast32_t rectHeight; ArrayValue aVal; uint_fast32_t counter = 0; int cancelRequested = CancelTaskRequested(threadArgHeader); Color color; for (uint_fast32_t i = 0; i < nbRectangles && !cancelRequested; ++i) { currentRect = &c_arg->rectangles[i]; rectHeight = currentRect->y2+1-currentRect->y1; for (uint_fast32_t j = currentRect->y1; j <= currentRect->y2 && !cancelRequested; ++j) { SetThreadProgress(threadArgHeader, 100 * (i*rectHeight+j) / (nbRectangles*rectHeight)); for (uint_fast32_t k = currentRect->x1; k <= currentRect->x2 && !cancelRequested; ++k) { HandleRequests(128); aVal = GetArrayValue(cache, k, j); if (isArrayValueValid(aVal, cache)) { color = GetColorFromAVal(aVal, render); PutPixelUnsafe(dst, k, j, color); } } } } SetThreadProgress(threadArgHeader, 100); int canceled = CancelTaskRequested(threadArgHeader); return (canceled ? PTHREAD_CANCELED : NULL); } char fillImageFromCacheArrayMessage[] = "Filling image from cache array"; Task *CreateFillImageFromCacheArrayTask(Image *dst, FractalCache *cache, const RenderingParameters *render, uint_fast32_t nbThreads) { if (dst->width == 0 || dst->height == 0) { return DoNothingTask(); } uint_fast32_t nbPixels = dst->width*dst->height; uint_fast32_t nbThreadsNeeded = nbThreads; uint_fast32_t rectanglesPerThread = DEFAULT_RECTANGLES_PER_THREAD; if (nbPixels <= nbThreadsNeeded) { nbThreadsNeeded = nbPixels; rectanglesPerThread = 1; } else if (nbPixels < nbThreadsNeeded*rectanglesPerThread) { rectanglesPerThread = nbPixels / nbThreadsNeeded; } uint_fast32_t nbRectangles = nbThreadsNeeded*rectanglesPerThread; UIRectangle *rectangle; rectangle = (UIRectangle *)safeMalloc("rectangles", nbRectangles * sizeof(UIRectangle)); InitUIRectangle(&rectangle[0], 0, 0, dst->width-1, dst->height-1); if (CutUIRectangleInN(rectangle[0], nbRectangles, rectangle)) { FractalNow_error("Could not cut rectangle ((%"PRIuFAST32",%"PRIuFAST32"),\ (%"PRIuFAST32",%"PRIuFAST32") in %"PRIuFAST32" parts.\n", rectangle[0].x1, rectangle[0].y1, rectangle[0].x2, rectangle[0].y2, nbRectangles); } FillImageFromCacheArrayArguments *arg; arg = (FillImageFromCacheArrayArguments *)safeMalloc("arguments", nbThreadsNeeded * sizeof(FillImageFromCacheArrayArguments)); for (uint_fast32_t i = 0; i < nbThreadsNeeded; ++i) { arg[i].threadId = i; arg[i].cache = cache; arg[i].image = dst; arg[i].render = render; arg[i].nbRectangles = rectanglesPerThread; arg[i].rectangles = &rectangle[i*rectanglesPerThread]; } Task *task = CreateTask(fillImageFromCacheArrayMessage, nbThreadsNeeded, arg, sizeof(FillImageFromCacheArrayArguments), FillImageFromCacheArrayThreadRoutine, FreeFillImageFromCacheArrayArguments); free(arg); return task; } void FillImageFromCacheArray(Image *dst, FractalCache *cache, const RenderingParameters *render, Threads *threads) { Task *task = CreateFillImageFromCacheArrayTask(dst, cache, render, threads->N); int unused = ExecuteTaskBlocking(task, threads); UNUSED(unused); } Task *CreateFillArrayAndImageFromCacheTask(FractalCache *cache, Image *image, const Fractal *fractal, const RenderingParameters *render, int fillImageOnTheFly, uint_fast32_t nbThreads) { Task *res; if (fillImageOnTheFly) { res = CreateFillCacheArrayTask(cache, image, fractal, render, nbThreads); } else { Task *subTasks[2]; subTasks[0] = CreateFillCacheArrayTask(cache, NULL, fractal, render, nbThreads); subTasks[1] = CreateFillImageFromCacheArrayTask(image, cache, render, nbThreads); res = CreateCompositeTask(NULL, 2, subTasks); } return res; } void FillArrayAndImageFromCache(FractalCache *cache, Image *image, const Fractal *fractal, const RenderingParameters *render, int fillImageOnTheFly, Threads *threads) { Task *task = CreateFillArrayAndImageFromCacheTask(cache, image, fractal, render, fillImageOnTheFly, threads->N); int unused = ExecuteTaskBlocking(task, threads); UNUSED(unused); } void aux_CreateFractalCachePreviewTask(FractalCache *cache, const Fractal *fractal, const RenderingParameters *render) { safePThreadSpinLock(&cache->entryMutex); cache->nbInitialized = 0; cache->currentIndex = 0; safePThreadSpinUnlock(&cache->entryMutex); if (cache->firstUse) { cache->firstUse = 0; } else { FreeFractal(*cache->fractal); FreeRenderingParameters(*cache->render); } *cache->fractal = CopyFractal(fractal); *cache->render = CopyRenderingParameters(render); } enum TaskType { DO_NOTHING=0, RESIZE_CLEAR, RESIZE_CLEAR_FILL, CLEAR_FILL, FILL }; static inline int PartCompareFractals(const Fractal *fractal1, const Fractal *fractal2) { return (fractal1->fractalFormula != fractal2->fractalFormula || !ceqBiggestF(fractal1->p, fractal2->p) || !ceqBiggestF(fractal1->c, fractal2->c) || fractal1->escapeRadius != fractal2->escapeRadius || fractal1->maxIter != fractal2->maxIter); } static inline int PartCompareRenderingParameters(const RenderingParameters *param1, const RenderingParameters *param2) { return (param1->bytesPerComponent != param2->bytesPerComponent || CompareColors(param1->spaceColor, param2->spaceColor) || param1->iterationCount != param2->iterationCount || param1->coloringMethod != param2->coloringMethod || param1->addendFunction != param2->addendFunction || param1->stripeDensity != param2->stripeDensity || param1->interpolationMethod != param2->interpolationMethod); } char fractalCachePreviewMessage[] = "Creating fractal preview from cache"; Task *CreateFractalCachePreviewTask(Image *dst, FractalCache *cache, const Fractal *fractal, const RenderingParameters *render, int fillImageOnTheFly, uint_fast32_t nbThreads) { Task *res; Fractal *cacheFractal = cache->fractal; RenderingParameters *cacheRender = cache->render; enum TaskType taskType; if (cache->firstUse) { aux_CreateFractalCachePreviewTask(cache, fractal, render); taskType = RESIZE_CLEAR; } else if (PartCompareFractals(cacheFractal, fractal) || PartCompareRenderingParameters(cacheRender, render)) { aux_CreateFractalCachePreviewTask(cache, fractal, render); if (dst->width != cache->arrayWidth || dst->height != cache->arrayHeight) { taskType = RESIZE_CLEAR; } else { int unused = InvalidateCacheArray(cache); UNUSED(unused); taskType = DO_NOTHING; } } else if (dst->width != cache->arrayWidth || dst->height != cache->arrayHeight) { taskType = RESIZE_CLEAR_FILL; } else { if (InvalidateCacheArray(cache)) { taskType = CLEAR_FILL; } else { taskType = FILL; } } switch (taskType) { case DO_NOTHING: { Task *subTask = DoNothingTask(); res = CreateCompositeTask(fractalCachePreviewMessage, 1, &subTask); break; } case RESIZE_CLEAR: { Task *subTasks[2]; subTasks[0] = CreateResizeCacheArrayTask(cache, dst->width, dst->height); subTasks[1] = CreateClearCacheArrayTask(cache, dst->width, dst->height, nbThreads); res = CreateCompositeTask(fractalCachePreviewMessage, 2, subTasks); break; } case RESIZE_CLEAR_FILL: { Task *subTasks[3]; subTasks[0] = CreateResizeCacheArrayTask(cache, dst->width, dst->height); subTasks[1] = CreateClearCacheArrayTask(cache, dst->width, dst->height, nbThreads); subTasks[2] = CreateFillArrayAndImageFromCacheTask(cache, dst, fractal, render, fillImageOnTheFly, nbThreads); res = CreateCompositeTask(fractalCachePreviewMessage, 3, subTasks); break; } case CLEAR_FILL: { Task *subTasks[2]; subTasks[0] = CreateClearCacheArrayTask(cache, dst->width, dst->height, nbThreads); subTasks[1] = CreateFillArrayAndImageFromCacheTask(cache, dst, fractal, render, fillImageOnTheFly, nbThreads); res = CreateCompositeTask(fractalCachePreviewMessage, 2, subTasks); break; } case FILL: { Task *subTask = CreateFillArrayAndImageFromCacheTask(cache, dst, fractal, render, fillImageOnTheFly, nbThreads); res = CreateCompositeTask(fractalCachePreviewMessage, 1, &subTask); } break; } return res; } void FractalCachePreview(Image *dst, FractalCache *cache, const Fractal *fractal, const RenderingParameters *render, int fillImageOnTheFly, Threads *threads) { Task *task = CreateFractalCachePreviewTask(dst, cache, fractal, render, fillImageOnTheFly, threads->N); int unused = ExecuteTaskBlocking(task, threads); UNUSED(unused); } void FreeFractalCache(FractalCache *cache) { for (uint_fast32_t i = 0; i < cache->nbInitialized; ++i) { FreeCacheEntry(cache->entry[i]); } free(cache->entry); for (uint_fast32_t i = 0; i < cache->arrayHeight; ++i) { free(cache->array[i]); } free(cache->array); if (!cache->firstUse) { FreeFractal(*cache->fractal); FreeRenderingParameters(*cache->render); } free(cache->fractal); free(cache->render); safePThreadSpinDestroy(&cache->entryMutex); safePThreadSpinDestroy(&cache->arrayMutex); } fractalnow-0.8.2/lib/include/macro_build_fractals.h000664 001750 001750 00000006446 13175115345 022325 0ustar00mpegmpeg000000 000000 /* * macro_build_fractals.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file macro_build_fractals.h * \brief Header file related to macros for building fractal loop functions. * * \author Marc Pegon */ #ifndef __MACRO_BUILD_FRACTALS_H__ #define __MACRO_BUILD_FRACTALS_H__ #ifdef __cplusplus extern "C" { #endif #define FLOAT_PRECISIONS(x,y,z,t,u,v,w) MACRO_BUILD_FRACTAL(x,y,z,t,u,v,w) #if defined(_ENABLE_MP_FLOATS) && defined(_ENABLE_LDOUBLE_FLOATS) #define BUILD_FLOAT_PRECISIONS(x,y,z,t,u,v) \ FLOAT_PRECISIONS(x,y,z,t,u,v,SINGLE) \ FLOAT_PRECISIONS(x,y,z,t,u,v,DOUBLE) \ FLOAT_PRECISIONS(x,y,z,t,u,v,LDOUBLE) \ FLOAT_PRECISIONS(x,y,z,t,u,v,MP) #elif defined(_ENABLE_MP_FLOATS) && !defined(_ENABLE_LDOUBLE_FLOATS) #define BUILD_FLOAT_PRECISIONS(x,y,z,t,u,v) \ FLOAT_PRECISIONS(x,y,z,t,u,v,SINGLE) \ FLOAT_PRECISIONS(x,y,z,t,u,v,DOUBLE) \ FLOAT_PRECISIONS(x,y,z,t,u,v,MP) #elif !defined(_ENABLE_MP_FLOATS) && defined(_ENABLE_LDOUBLE_FLOATS) #define BUILD_FLOAT_PRECISIONS(x,y,z,t,u,v) \ FLOAT_PRECISIONS(x,y,z,t,u,v,SINGLE) \ FLOAT_PRECISIONS(x,y,z,t,u,v,LDOUBLE) \ FLOAT_PRECISIONS(x,y,z,t,u,v,DOUBLE) #else #define BUILD_FLOAT_PRECISIONS(x,y,z,t,u,v) \ FLOAT_PRECISIONS(x,y,z,t,u,v,SINGLE) \ FLOAT_PRECISIONS(x,y,z,t,u,v,DOUBLE) #endif #define INTERPOLATION_METHOD(x,y,z,t,u,v) BUILD_FLOAT_PRECISIONS(x,y,z,t,u,v) #define BUILD_INTERPOLATION_METHODS(x,y,z,t,u) \ INTERPOLATION_METHOD(x,y,z,t,u,NONE) \ INTERPOLATION_METHOD(x,y,z,t,u,LINEAR) \ INTERPOLATION_METHOD(x,y,z,t,u,SPLINE) #define ADDEND_FUNCTION(x,y,z,t,u) BUILD_INTERPOLATION_METHODS(x,y,z,t,u) #define BUILD_ADDEND_FUNCTIONS(x,y,z,t) \ ADDEND_FUNCTION(x,y,z,t,TRIANGLEINEQUALITY) \ ADDEND_FUNCTION(x,y,z,t,CURVATURE) \ ADDEND_FUNCTION(x,y,z,t,STRIPE) #define ITERATION_COUNT(x,y,z,t) BUILD_ADDEND_FUNCTIONS(x,y,z,t) #define BUILD_ITERATION_COUNTS(x,y,z) \ ITERATION_COUNT(x,y,z,DISCRETE)\ ITERATION_COUNT(x,y,z,CONTINUOUS)\ ITERATION_COUNT(x,y,z,SMOOTH) #define COLORING_METHOD(x,y,z) BUILD_ITERATION_COUNTS(x,y,z) #define BUILD_COLORING_METHODS(x,y) \ COLORING_METHOD(x,y,ITERATIONCOUNT) \ COLORING_METHOD(x,y,AVERAGECOLORING) #define P_TYPE(x,y) BUILD_COLORING_METHODS(x,y) #define BUILD_P_TYPES(x) \ P_TYPE(x,PINT) \ P_TYPE(x,PFLOATT) #define FORMULA(x) BUILD_P_TYPES(x) #define BUILD_FORMULAS \ FORMULA(MANDELBROT)\ FORMULA(MULTIBROT)\ FORMULA(JULIA)\ FORMULA(MULTIJULIA)\ FORMULA(BURNINGSHIP)\ FORMULA(JULIABURNINGSHIP)\ FORMULA(MANDELBAR)\ FORMULA(JULIABAR)\ FORMULA(RUDY) #define MACRO_BUILD_FRACTALS BUILD_FORMULAS #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/rendering_files/render02a.render000664 001750 001750 00000000116 13175112471 023545 0ustar00mpegmpeg000000 000000 R075 1 0x0 ITERATIONCOUNT SMOOTH LOG 2.5E-1 0.5 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/lib/include/gradient.h000664 001750 001750 00000017674 13175115345 017770 0ustar00mpegmpeg000000 000000 /* * gradient.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file gradient.h * \brief Header file related to gradients. * \author Marc Pegon */ #ifndef __GRADIENT_H__ #define __GRADIENT_H__ #include "color.h" #include #include #ifdef __cplusplus extern "C" { #endif /** * \def DEFAULT_GRADIENT_TRANSITIONS * \brief Default number of transitions between two colors used for gradient. */ #define DEFAULT_GRADIENT_TRANSITIONS (uint_fast32_t)(UINT16_MAX+1) /** * \def DEFAULT_GRADIENT_SIZE * \brief Default gradient size (total number of colors). */ #define DEFAULT_GRADIENT_SIZE (uint_fast32_t)(200000) /** * \struct Gradient * \brief Simple gradient structure. * * This structure is to represent a gradient, i.e. continous * transitions between colors. */ /** * \typedef Gradient * \brief Convenient typedef for struct Gradient. */ typedef struct Gradient { uint_fast8_t bytesPerComponent; /*!< Colors bytes per component.*/ uint_fast64_t size; /*!< Gradient size (total number of colors).*/ Color *data; /*!< Gradient data.*/ uint_fast32_t nbStops; /*!< Number of stops i.e. (pos,color) pairs used to build the gradient.*/ double *positionStop; /*!< Stops positions. */ Color *colorStop; /*!< Stops colors. */ } Gradient; /** * \fn void GenerateGradient(Gradient *gradient, uint_fast32_t nbStops, double *positionStop, Color *colorStop, uint_fast32_t size) * \brief Generate a gradient. * * Number of stops must be > 2 (exit program with error otherwise).\n * Position stops must begin with 0, end with 1, and be strictly * increasing (exit program with error otherwise).\n * Gradient size must be stricly positive (exit program with * error otherwise).\n * All the colors in given array must have the same number of bytes * per component (undefined behaviour otherwise). * * \param gradient Pointer to the (already allocated) gradient structure to initialize. * \param nbStops Number of stops (different colors) for gradient. * \param positionStop Position stops. * \param colorStop Color stops. * \param size Gradient size. */ void GenerateGradient(Gradient *gradient, uint_fast32_t nbStops, double *positionStop, Color *colorStop, uint_fast32_t size); /** * \fn void GenerateGradient2(Gradient *gradient, uint_fast32_t nbStops, Color *colorStop, uint_fast32_t nbTransitions) * \brief Generate a gradient. * * Generate a gradient from colors stops and the number of transitions * between two colors.\n * Number of stops must be > 2 (exit with error otherwise).\n * All the colors in given array must have the same number of bytes * per component (undefined behaviour otherwise).\n * Number of transitions must be strictly positive (exit program with * error otherwise). * * \param gradient Pointer to the (already allocated) gradient structure to initialize. * \param nbStops Number of stops (different colors) for gradient. * \param colorStop Color stops. * \param nbTransitions Number of transitions between two colors in the gradient. */ void GenerateGradient2(Gradient *gradient, uint_fast32_t nbStops, Color *colorStop, uint_fast32_t nbTransitions); /** * \fn int isSupportedGradientFile(const char *fileName) * \brief Check whether a file is a supported gradient file. * * \param fileName File name. * \return 1 if file is a supported gradient file, 0 otherwise. */ int isSupportedGradientFile(const char *fileName); /** * \fn int ReadGradientFileBody(Gradient *gradient, uint_fast8_t bytesPerComponent, const char *fileName, FILE *file, const char *format) * \brief Create gradient from gradient file body. * * The body of a gradient file is everything that comes after * the format version and the bytes per component.\n * fileName is used only for error messages.\n * This function should only be used internally by the library. * * \param gradient Pointer to the gradient structure to create. * \param bytesPerComponent Gradient file bytes per component (read from header). * \param fileName Gradient file name. * \param file Pointer to opened file, positioned at the beginning of the body. * \param format Gradient file format. * \return 0 in case of success, 1 in case of failure. */ int ReadGradientFileBody(Gradient *gradient, uint_fast8_t bytesPerComponent, const char *fileName, FILE *file, const char *format); /** * \fn int ReadGradientFile(Gradient *gradient, const char *fileName) * \brief Read and parse a gradient file, and create the according gradient. * * \param gradient Pointer to the gradient structure to create. * \param fileName Gradient file name. * \return 0 in case of success, 1 in case of failure. */ int ReadGradientFile(Gradient *gradient, const char *fileName); /** * \fn int WriteGradientFileBody(const Gradient *gradient, const char *fileName, FILE *file, const char *format) * \brief Write gradient file body. * * The body of a gradient file is everything that comes after * the format version and the bytes per component.\n * fileName is used only for error messages.\n * This function should only be used internally by the library. * * \param gradient Gradient to write into file. * \param fileName Gradient file name. * \param file Pointer to opened file, positioned at the beginning of the body. * \param format Gradient file format. * \return 0 in case of success, 1 in case of failure. */ int WriteGradientFileBody(const Gradient *gradient, const char *fileName, FILE *file, const char *format); /** * \fn int WriteGradientFile(const Gradient *gradient, const char *fileName) * \brief Write gradient into file. * * \param gradient Gradient to write into file. * \param fileName Gradient file name. * \return 0 in case of success, 1 in case of failure. */ int WriteGradientFile(const Gradient *gradient, const char *fileName); /** * \fn Gradient CopyGradient(const Gradient *gradient) * \brief Copy gradient. * * \param gradient Pointer to gradient to copy. * \return Copy of gradient. */ Gradient CopyGradient(const Gradient *gradient); /** * \fn Gradient Gradient16(const Gradient *gradient) * \brief Convert gradient to 16 bits gradient. * * Simple copy if gradient colors depth is already 16. * * \param gradient Pointer to gradient to be converted. * \return Newly-allocated 16 bits gradient. */ Gradient Gradient16(const Gradient *gradient); /** * \fn Gradient Gradient8(const Gradient *gradient) * \brief Convert gradient to 8 bits gradient. * * Simple copy if gradient colors depth is already 8. * * \param gradient Pointer to gradient to be converted. * \return Newly-allocated 8 bits gradient. */ Gradient Gradient8(const Gradient *gradient); /** * \fn Color GetGradientColor(const Gradient *gradient, uint_fast64_t index) * \brief Get a color in the gradient. * * Get the color in gradient at position index mod gradient_size * * \param gradient Pointer to the gradient to get the color from. * \param index (mod.) Index of the color to get. * \return Color in gradient at position (index mod gradient_size). */ Color GetGradientColor(const Gradient *gradient, uint_fast64_t index); /** * \fn void FreeGradient(Gradient gradient) * \brief Free gradient. * * \param gradient Gradient to be freed. */ void FreeGradient(Gradient gradient); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/gradient_files/gradient01b.gradient000664 001750 001750 00000000124 13175112471 024220 0ustar00mpegmpeg000000 000000 G073 2 0 0xFFFF 0.25 0xFFFFFFFFFFFF 0.5 0xFFFFFFFF0000 0.75 0xFFFF00000000 1 0xFFFF fractalnow-0.8.2/lib/include/ppm.h000664 001750 001750 00000002756 13175112471 016757 0ustar00mpegmpeg000000 000000 /* * ppm.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file ppm.h * \brief Header file related to PPM (Portable Pixmap) handling. * \author Marc Pegon */ #ifndef __PPM_H__ #define __PPM_H__ #include "image.h" #include #ifdef __cplusplus extern "C" { #endif /** * \fn int ExportPPM(const char *fileName, const Image *image) * \brief Export image as PPM; * * If file specified by fileName already exists, it will * be overwritten. * * \param fileName Name of the PPM file to export the image in. * \param image Pointer to image structure to export. * \return 0 in case of success, 0 in case of error. */ int ExportPPM(const char *fileName, const Image *image); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/gradient_files/gradient01a.gradient000664 001750 001750 00000000076 13175112471 024225 0ustar00mpegmpeg000000 000000 G073 1 0 0xFF 0.25 0xFFFFFF 0.5 0xFFFF00 0.75 0xFF0000 1 0xFF fractalnow-0.8.2/gui/qfractalnow.desktop000664 001750 001750 00000000327 13175115345 020314 0ustar00mpegmpeg000000 000000 [Desktop Entry] Version=1.0 Type=Application Name=QFractalNow GenericName=Fractal Generator Comment=Fractal images generator Icon=qfractalnow Exec=qfractalnow -q Categories=Qt;Education;Science;Math; Terminal=false fractalnow-0.8.2/lib/include/thread.h000664 001750 001750 00000025634 13175112471 017432 0ustar00mpegmpeg000000 000000 /* * thread.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file thread.h * \brief Header file related to threads. * \author Marc Pegon */ #ifndef __THREAD_H__ #define __THREAD_H__ #include #include #include #ifndef PTHREAD_CANCELED #define PTHREAD_CANCELED ((void *) -1) #endif #ifdef __cplusplus extern "C" { #endif /** * \def DEFAULT_NB_THREADS * \brief Default number of threads. */ #define DEFAULT_NB_THREADS (uint_fast32_t)(4) /** * \def DEFAULT_RECTANGLES_PER_THREAD * \brief Default number of rectangles per thread. * * Used for working on images. Each thread * may be assigned a number of rectangles * to draw. * This can be used to distribute homogeneously * the work between threads. * Although it can be disturbing if the user can * view the progress of the action in real-time * (small rectangles being drawn erratically), * which is why this is 1 by default. * * Not that a workaround to distribute the work * more homogeneously is simply to create more * threads than machine cores. */ #define DEFAULT_RECTANGLES_PER_THREAD (uint_fast32_t)(1) // thread related #define THREAD_CREATE_ERROR "Thread create error" #define THREAD_CANCEL_ERROR "Thread cancel error" #define THREAD_JOIN_ERROR "Thread join error" #define THREAD_MUTEX_INIT_ERROR "Thread mutex init error" #define THREAD_MUTEX_LOCK_ERROR "Thread mutex lock error" #define THREAD_MUTEX_UNLOCK_ERROR "Thread mutex unlock error" #define THREAD_MUTEX_DESTROY_ERROR "Thread mutex destroy error" #define THREAD_COND_INIT_ERROR "Thread cond init error" #define THREAD_COND_WAIT_ERROR "Thread cond wait error" #define THREAD_COND_SIGNAL_ERROR "Thread cond signal error" #define THREAD_COND_BROADCAST_ERROR "Thread cond broadcast error" #define THREAD_COND_DESTROY_ERROR "Thread cond destroy error" #define safePThreadCreate(thread,attributes,startRoutine,argument) {if((errno=pthread_create(thread,attributes,startRoutine,argument))!=0){perror(THREAD_CREATE_ERROR);exit(EXIT_FAILURE);}} #define safePThreadJoin(thread,status); {if((errno=pthread_join(thread,status))!=0){perror(THREAD_JOIN_ERROR);exit(EXIT_FAILURE);}} #define safePThreadMutexInit(mutex,attributes) {if((errno=pthread_mutex_init(mutex,attributes))!=0){perror(THREAD_MUTEX_INIT_ERROR);exit(EXIT_FAILURE);}} #define safePThreadMutexLock(mutex) {if((errno=pthread_mutex_lock(mutex))!=0){perror(THREAD_MUTEX_LOCK_ERROR);exit(EXIT_FAILURE);}} #define safePThreadMutexUnlock(mutex) {if((errno=pthread_mutex_unlock(mutex))!=0){perror(THREAD_MUTEX_UNLOCK_ERROR);perror(THREAD_MUTEX_UNLOCK_ERROR);exit(EXIT_FAILURE);}} #define safePThreadMutexDestroy(mutex) {if((errno=pthread_mutex_destroy(mutex))!=0){perror(THREAD_MUTEX_DESTROY_ERROR);exit(EXIT_FAILURE);}} #define safePThreadCondInit(cond,attributes) {if((errno=pthread_cond_init(cond,attributes))!=0){perror(THREAD_COND_INIT_ERROR);exit(EXIT_FAILURE);}} #define safePThreadCancel(thread) {if((errno=pthread_cancel(thread))!=0){perror(THREAD_CANCEL_ERROR);exit(EXIT_FAILURE);}} #define safePThreadCondWait(cond,mutex) {if((errno=pthread_cond_wait(cond,mutex))!=0){perror(THREAD_COND_WAIT_ERROR);exit(EXIT_FAILURE);}} #define safePThreadCondSignal(cond) {if((errno=pthread_cond_signal(cond))!=0){perror(THREAD_COND_SIGNAL_ERROR);exit(EXIT_FAILURE);}} #define safePThreadCondBroadcast(cond) {if((errno=pthread_cond_broadcast(cond))!=0){perror(THREAD_COND_BROADCAST_ERROR);exit(EXIT_FAILURE);}} #define safePThreadCondDestroy(cond) {if((errno=pthread_cond_destroy(cond))!=0){perror(THREAD_COND_DESTROY_ERROR);exit(EXIT_FAILURE);}} #ifdef NO_SPINLOCK #define THREAD_SPIN_INIT_ERROR THREAD_MUTEX_INIT_ERROR #define THREAD_SPIN_LOCK_ERROR THREAD_MUTEX_LOCK_ERROR #define THREAD_SPIN_UNLOCK_ERROR THREAD_MUTEX_UNLOCK_ERROR #define THREAD_SPIN_DESTROY_ERROR THREAD_MUTEX_DESTROY_ERROR #define safePThreadSpinInit(mutex,attributes) safePThreadMutexInit(mutex,attributes) #define safePThreadSpinLock(mutex) safePThreadMutexLock(mutex) #define safePThreadSpinUnlock(mutex) safePThreadMutexUnlock(mutex) #define safePThreadSpinDestroy(mutex) safePThreadMutexDestroy(mutex) #define pthread_spinlock_t pthread_mutex_t #define SPIN_INIT_ATTR NULL #else #define THREAD_SPIN_INIT_ERROR "Thread spin init error" #define THREAD_SPIN_LOCK_ERROR "Thread spin lock error" #define THREAD_SPIN_UNLOCK_ERROR "Thread spin unlock error" #define THREAD_SPIN_DESTROY_ERROR "Thread spin destroy error" #define safePThreadSpinInit(mutex,attributes) {if((errno=pthread_spin_init(mutex,attributes))!=0){perror(THREAD_SPIN_INIT_ERROR);exit(EXIT_FAILURE);}} #define safePThreadSpinLock(mutex) {if((errno=pthread_spin_lock(mutex))!=0){perror(THREAD_SPIN_LOCK_ERROR);exit(EXIT_FAILURE);}} #define safePThreadSpinUnlock(mutex) {if((errno=pthread_spin_unlock(mutex))!=0){perror(THREAD_SPIN_UNLOCK_ERROR);perror(THREAD_SPIN_UNLOCK_ERROR);exit(EXIT_FAILURE);}} #define safePThreadSpinDestroy(mutex) {if((errno=pthread_spin_destroy(mutex))!=0){perror(THREAD_SPIN_DESTROY_ERROR);exit(EXIT_FAILURE);}} #define SPIN_INIT_ATTR PTHREAD_PROCESS_PRIVATE #endif struct StartThreadArg; /** * \struct Threads * \brief Threads structure. * * Threads should be created on program startup, and destroyed * on exit.\n * Once created, threads can be used to launch actions, such * as drawing fractals, applying filters on images, etc.. */ /** * \typedef Threads * \brief Convenient typedef for struct Threads. */ typedef struct Threads { uint_fast32_t N; /*!< N Number of threads in this structure.*/ uint_fast32_t nbReady; /*!< Number of threads ready to launch a new task.*/ uint_fast32_t nbPaused; /*!< Number of threads currently paused (waiting resumeTaskCond to be signaled).*/ pthread_mutex_t startThreadCondMutex; /*!< Mutex for starting threads condition.*/ pthread_cond_t startThreadCond; /*!< Condition signaled when thread should start working on a new task.*/ pthread_mutex_t threadsMutex; /*!< Main threads mutex (multiple use).*/ pthread_cond_t allThreadsReadyCond; /*!< Condition signaled when all threads are ready to launch a new task.*/ pthread_cond_t allPausedCond; /*!< Condition signaled when all active threads have been paused.*/ pthread_cond_t allResumedCond; /*!< Condition signaled when all previously paused threads have resumed.*/ pthread_cond_t resumeTaskCond; /*!< Condition signaled when resume task is requested.*/ pthread_t *thread; /*!< Pthreads array.*/ struct StartThreadArg *startThreadArg; /*!< Start thread argument.*/ void **lastResult; /*!< Last result for each thread.*/ } Threads; /** * \struct ThreadArgHeader * \brief Thread argument header. */ /** * \typedef ThreadArgHeader * \brief Convenient typedef for struct ThreadArgHeader. */ typedef struct ThreadArgHeader { uint_fast32_t threadId; /*!< Id of thread working on this argument.*/ Threads *threads; /*!< Pointer to threads structure.*/ uint_fast32_t *nbReady; /*!< Number of threads ready for next task, OR subtask (for composite tasks). This does not necessarily points to threads->nbWaiting.*/ int *cancel; /*!< Used by thread to receive cancellation request.*/ pthread_spinlock_t *cancelMutex; /*!< Mutex for cancel variable.*/ int *pause; /*!< Used to pause thread.*/ pthread_spinlock_t *pauseMutex; /*!< Mutex for pause variable.*/ int progress; /*!< Should be kept up-to-date by thread to give an hint on its progress (value between 0 and 100).*/ pthread_spinlock_t progressMutex; /*!< Mutex for progress variable.*/ } ThreadArgHeader; /** * \struct StartThreadArg * \brief Structure used to start tasks (for internal use). */ /** * \typedef StartThreadArg * \brief Convenient typedef for struct StartThreadArg. */ typedef struct StartThreadArg { uint_fast32_t threadId; /*!< Thread id (between 0 and threads->N-1.*/ Threads *threads; /*!< Threads structure.*/ char *message; /*!< Pointer to threads structure (convenient to access threads common variables).*/ void *(*startRoutine)(void *arg); /*!< Routine to be launched by thread (task routine).*/ void *arg; /*!< Argument to be passed to thread routine.*/ void **result; /*!< Where to put startRoutine return value.*/ } StartThreadArg; /** * \fn Threads *CreateThreads(uint_fast32_t N) * \brief Create threads. * * \param N Number of threads to be created. * \return Newly-allocated threads structure. */ Threads *CreateThreads(uint_fast32_t N); /** * \fn void DestroyThreads(Threads *threads) * \brief Destroy threads. * * Threads should not be busy.\n * Function is blocking, i.e. will wait for threads to * finish before destroying them. * * \param threads Threads structure to destroy and free. */ void DestroyThreads(Threads *threads); /** * \fn ThreadArgHeader *GetThreadArgHeader(const void *arg) * \brief Get header part of thread argument. * * \param arg Argument passed to thread routine. * \return Header part of thread argument. */ ThreadArgHeader *GetThreadArgHeader(const void *arg); /** * \fn void *GetThreadArgBody(const void *arg) * \brief Get body (user) part of thread argument. * * \param arg Argument passed to thread routine. * \return Body part of thread argument (i.e. pointer to argument passed by user when launching action). */ void *GetThreadArgBody(const void *arg); /** * \fn int CancelTaskRequested(ThreadArgHeader *threadArgHeader) * \brief Query task cancelation request, through argument header. * * This function is thread-safe. * * \param threadArgHeader Thread argument header. * \return 1 if cancelation request has been made, 0 otherwise. */ int CancelTaskRequested(ThreadArgHeader *threadArgHeader); /** * \fn int SetThreadProgress(ThreadArgHeader *threadArgHeader, int progress) * \brief Set thread progress, through argument header. * * This function is thread-safe. * Progress should be a value between 0 and 100 (unspecified behaviour * otherwise). * * \param threadArgHeader Thread argument header. * \param progress Task progress. */ void SetThreadProgress(ThreadArgHeader *threadArgHeader, int progress); /** * \fn void HandlePauseRequest(ThreadArgHeader *threadArgHeader) * \brief Handle pause request. * * Blocks if task has been paused, until task is resumed. * \see task.c * * \param threadArgHeader Thread argument header. */ void HandlePauseRequest(ThreadArgHeader *threadArgHeader); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/gui/include/fractal_config_widget.h000664 001750 001750 00000003542 13175112471 022477 0ustar00mpegmpeg000000 000000 /* * fractal_config_widget.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal_config_widget.h * \brief Header file introducing FractalConfigWidget class. * * \author Marc Pegon */ #ifndef __FRACTAL_CONFIG_WIDGET_H__ #define __FRACTAL_CONFIG_WIDGET_H__ #include "mpfr_spin_box.h" #include "fractalnow.h" #include #include #include class FractalConfigWidget : public QWidget { Q_OBJECT public: FractalConfigWidget(const Fractal &fractal); QComboBox *fractalFormulaComboBox; MPFRSpinBox *pParamReSpinBox; MPFRSpinBox *pParamImSpinBox; MPFRSpinBox *cParamReSpinBox; MPFRSpinBox *cParamImSpinBox; MPFRSpinBox *centerXSpinBox; MPFRSpinBox *centerYSpinBox; MPFRSpinBox *spanXSpinBox; QDoubleSpinBox *bailoutRadiusSpinBox; QSpinBox *maxIterationsSpinBox; private: void blockBoxesSignals(bool block); public slots: void updateBoxesValues(const Fractal &fractal); private slots: void updateSpaceBoxesSingleSteps(); void updateCParamReSingleStep(); void updateCParamImSingleStep(); void updateBoxesEnabledValue(); }; #endif fractalnow-0.8.2/gui/src/mpfr_spin_box.cpp000664 001750 001750 00000014764 13175112471 020547 0ustar00mpegmpeg000000 000000 /* * mpfr_spin_box.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "mpfr_spin_box.h" #include MPFRSpinBox::MPFRSpinBox(QWidget * parent) : QAbstractSpinBox(parent) { m_notation = ClassicNotation; m_decimals = -1; mpfr_init(m_value); mpfr_set_ui(m_value, 0, MPFR_RNDN); mpfr_init(m_singleStep); mpfr_set_ui(m_singleStep, 1, MPFR_RNDN); mpfr_init(m_minimum); mpfr_init(m_maximum); mpfr_set_ui_2exp(m_maximum, 1, 99.99, MPFR_RNDN); mpfr_set_ui(m_minimum, 0, MPFR_RNDN); mpfr_t initValue; mpfr_init(initValue); mpfr_set_d(initValue, 0.5, MPFR_RNDN); setValue(&initValue); mpfr_clear(initValue); connect(lineEdit(), SIGNAL(textEdited(const QString &)), this, SLOT(onTextEdited(const QString &))); connect(lineEdit(), SIGNAL(editingFinished()), this, SLOT(onEditingFinished())); } MPFRSpinBox::~MPFRSpinBox() { mpfr_clear(m_value); mpfr_clear(m_singleStep); mpfr_clear(m_minimum); mpfr_clear(m_maximum); } void MPFRSpinBox::aux_setMaximum() { /* Update m_value and/or m_minimum if needed after maximum has changed. */ if (mpfr_cmp(m_maximum, m_minimum) < 0) { mpfr_set(m_minimum, m_maximum, MPFR_RNDN); } if (mpfr_cmp(m_value, m_minimum) < 0) { setValue(&m_minimum); } } void MPFRSpinBox::setMaximum ( const mpfr_t * max ) { mpfr_set(m_maximum, *max, MPFR_RNDN); aux_setMaximum(); } void MPFRSpinBox::setMaximum ( long double max ) { mpfr_set_ld(m_maximum, max, MPFR_RNDN); aux_setMaximum(); } void MPFRSpinBox::aux_setMinimum() { /* Update m_value and/or m_maximum if needed after minimum has changed. */ if (mpfr_cmp(m_minimum, m_maximum) > 0) { mpfr_set(m_maximum, m_minimum, MPFR_RNDN); } if (mpfr_cmp(m_value, m_maximum) > 0) { setValue(&m_maximum); } } void MPFRSpinBox::setMinimum ( const mpfr_t * min ) { mpfr_set(m_minimum, *min, MPFR_RNDN); aux_setMinimum(); } void MPFRSpinBox::setMinimum ( long double min ) { mpfr_set_ld(m_minimum, min, MPFR_RNDN); aux_setMinimum(); } void MPFRSpinBox::setRange ( const mpfr_t * min, const mpfr_t * max) { setMinimum(min); setMaximum(max); } void MPFRSpinBox::setRange ( long double min, long double max ) { setMinimum(min); setMaximum(max); } void MPFRSpinBox::setSingleStep ( const mpfr_t * val ) { mpfr_set(m_singleStep, *val, MPFR_RNDN); } void MPFRSpinBox::setSingleStep ( long double val ) { mpfr_set_ld(m_singleStep, val, MPFR_RNDN); } void MPFRSpinBox::setNotation ( Notation notation ) { if (notation != m_notation) { m_notation = notation; updateText(); } } void MPFRSpinBox::setDecimals ( int prec ) { if (prec != m_decimals) { m_decimals = prec; updateText(); } } void MPFRSpinBox::updateText() { lineEdit()->setText(textFromValue(&m_value)); } void MPFRSpinBox::fixup( QString & input ) const { Q_UNUSED(input); } void MPFRSpinBox::stepBy(int step) { mpfr_t newValue; mpfr_init(newValue); mpfr_mul_si(newValue, m_singleStep, step, MPFR_RNDN); mpfr_add(newValue, newValue, m_value, MPFR_RNDN); setValue(&newValue); mpfr_clear(newValue); } const mpfr_t *MPFRSpinBox::value() { return &m_value; } long double MPFRSpinBox::value_d() { return mpfr_get_ld(m_value, MPFR_RNDN); } inline bool MPFRSpinBox::isInRange(const mpfr_t val) const { return (mpfr_cmp(val,m_minimum) >= 0 && mpfr_cmp(val,m_maximum) <= 0); } inline void MPFRSpinBox::aux_setValue(const mpfr_t *val) { bool changed = (mpfr_cmp(m_value, *val) != 0); mpfr_set(m_value, *val, MPFR_RNDN); if (changed) { emit valueChanged(&m_value); } } inline void MPFRSpinBox::setValue(const mpfr_t *val, bool updateText) { if (mpfr_cmp(*val, m_minimum) < 0) { aux_setValue(&m_minimum); } else if (mpfr_cmp(*val, m_maximum) > 0) { aux_setValue(&m_maximum); } else { aux_setValue(val); } if (updateText) this->updateText(); } void MPFRSpinBox::setValue(const mpfr_t *val) { setValue(val, true); } inline void MPFRSpinBox::aux_setValue(long double val) { bool changed = (mpfr_cmp_ld(m_value, val) != 0); mpfr_set_ld(m_value, val, MPFR_RNDN); if (changed) { emit valueChanged(&m_value); } } void MPFRSpinBox::setValue(long double val) { if (mpfr_cmp_ld(m_minimum, val) > 0) { aux_setValue(&m_minimum); } else if (mpfr_cmp_ld(m_maximum, val) < 0) { aux_setValue(&m_maximum); } else { aux_setValue(val); } this->updateText(); } QValidator::State MPFRSpinBox::validate ( QString & input, int & pos ) const { Q_UNUSED(pos); FILE *tmp = tmpfile(); fputs(input.toStdString().c_str(), tmp); rewind(tmp); mpfr_t dst; mpfr_init(dst); QValidator::State res = QValidator::Invalid; if (mpfr_inp_str(dst, tmp, 10, MPFR_RNDN) != 0 && isInRange(dst)) { res = QValidator::Acceptable; } mpfr_clear(dst); fclose(tmp); return res; } mpfr_t *MPFRSpinBox::valueFromText(const QString &text) const { FILE *tmp = tmpfile(); fputs(text.toStdString().c_str(), tmp); rewind(tmp); mpfr_t *res = (mpfr_t *)malloc(sizeof(mpfr_t)); mpfr_init(*res); mpfr_inp_str(*res, tmp, 10, MPFR_RNDN); return res; } QString MPFRSpinBox::textFromValue(const mpfr_t *val) const { char *str; switch(m_notation) { case ClassicNotation: mpfr_asprintf(&str, "%.*Rf", (m_decimals < 0) ? mpfr_get_prec(*val) : m_decimals, *val); break; case ScientificNotation: if (m_decimals < 0) { mpfr_asprintf(&str, "%RE", *val); } else { mpfr_asprintf(&str, "%.*RE", m_decimals, *val); } break; } QString res(str); mpfr_free_str(str); return res; } QAbstractSpinBox::StepEnabled MPFRSpinBox::stepEnabled() const { StepEnabled res = 0; if (mpfr_cmp(m_value, m_minimum) > 0) { res |= StepDownEnabled; } if (mpfr_cmp(m_value, m_maximum) < 0) { res |= StepUpEnabled; } return res; } void MPFRSpinBox::onTextEdited(const QString & text) { mpfr_t *value = valueFromText(text); setValue(value, false); mpfr_clear(*value); free(value); } void MPFRSpinBox::onEditingFinished() { updateText(); } fractalnow-0.8.2/gui/000775 001750 001750 00000000000 13175146272 014401 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/gui/src/gradient_editor.cpp000664 001750 001750 00000007042 13175125262 021036 0ustar00mpegmpeg000000 000000 /**************************************************************************** ** ** This file is based on some files of the demonstration applications of the ** Qt Toolkit. ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Modified to be used as a part of FractalNow: ** Copyright (c) 2012 Marc Pegon ** ** This file can be distributed and/or modified under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation. ** You should have received a copy of the GNU General Public License ** along with this file; if not, write to the Free Software Foundation, Inc., ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ** ****************************************************************************/ #include "gradient_editor.h" #include GradientEditor::GradientEditor(QWidget *parent) : QWidget(parent) { QVBoxLayout *vbox = new QVBoxLayout; vbox->setSpacing(1); vbox->setMargin(1); m_gradient_label = new GradientLabel; m_red_shade = new ShadeWidget(ShadeWidget::RedShade); m_green_shade = new ShadeWidget(ShadeWidget::GreenShade); m_blue_shade = new ShadeWidget(ShadeWidget::BlueShade); vbox->addWidget(m_gradient_label); vbox->addWidget(m_red_shade); vbox->addWidget(m_green_shade); vbox->addWidget(m_blue_shade); setLayout(vbox); connect(m_red_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated())); connect(m_green_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated())); connect(m_blue_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated())); } inline static bool x_less_than(const QPointF &p1, const QPointF &p2) { return p1.x() < p2.x(); } void GradientEditor::pointsUpdated() { qreal w = m_red_shade->width(); QGradientStops stops; QPolygonF points; points += m_red_shade->points(); points += m_green_shade->points(); points += m_blue_shade->points(); qSort(points.begin(), points.end(), x_less_than); for (int i=0; i0 && int(x) == int(points.at(i-1).x())) { continue; } QColor color((0x00ff0000 & m_red_shade->colorAt(int(x))) >> 16, (0x0000ff00 & m_green_shade->colorAt(int(x))) >> 8, (0x000000ff & m_blue_shade->colorAt(int(x)))); if (x / w > 1) { return; } stops << QGradientStop(x / w, color); } m_gradient_label->setGradientStops(stops); emit gradientStopsChanged(stops); } static void set_shade_points(const QPolygonF &points, ShadeWidget *shade) { shade->hoverPoints()->setPoints(points); shade->hoverPoints()->setPointLock(0, HoverPoints::LockToLeft); shade->hoverPoints()->setPointLock(points.size() - 1, HoverPoints::LockToRight); shade->update(); } void GradientEditor::setGradientStops(const QGradientStops &stops) { QPolygonF pts_red, pts_green, pts_blue; m_gradient_label->setGradientStops(stops); qreal h_red = m_red_shade->height(); qreal h_green = m_green_shade->height(); qreal h_blue = m_blue_shade->height(); for (int i=0; iwidth(), h_red - qRed(color) * h_red / 255); pts_green << QPointF(pos * m_green_shade->width(), h_green - qGreen(color) * h_green / 255); pts_blue << QPointF(pos * m_blue_shade->width(), h_blue - qBlue(color) * h_blue / 255); } set_shade_points(pts_red, m_red_shade); set_shade_points(pts_green, m_green_shade); set_shade_points(pts_blue, m_blue_shade); } fractalnow-0.8.2/command-line/include/help.h000664 001750 001750 00000002265 13175112471 020703 0ustar00mpegmpeg000000 000000 /* * help.h -- part of FractalNow * * Copyright (c) 2011 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #ifndef __HELP_H__ #define __HELP_H__ #include "fractalnow.h" #include #ifdef __cplusplus extern "C" { #endif /** * \fn void DisplayHelp() * \brief Display program help. */ void DisplayHelp(); #define invalid_use_error(...) \ FractalNow_message(stderr, T_QUIET, __VA_ARGS__);\ DisplayHelp();\ exit(EXIT_FAILURE) #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/lib/include/fractal_addend_function.h000664 001750 001750 00000027310 13175115345 022777 0ustar00mpegmpeg000000 000000 /* * fractal_addend_function.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file fractal_addend_function.h * \brief Header file related to fractal addend functions. * \author Marc Pegon */ #ifndef __FRACTAL_ADDEND_FUNCTION_H__ #define __FRACTAL_ADDEND_FUNCTION_H__ #include "float_precision.h" #include #ifdef __cplusplus extern "C" { #endif /** * \enum e_AddendFunction * \brief Fractal addend function. * * Addend functions are used to compute values of fractal * in case of average coloring (CM_AVERAGECOLORING). * * Addend functions are described by a sequence of instructions * at the initialization of the fractal loop, for each iteration, * and at the end of the fractal loop.\n * They take for parameter 'size' the number of average sums to * be computed. Those sums SN[0], SN[1], ..., SN[size-1] *must* * be computed (at least initialized) by the addend function, * since they will be used by the interpolation method. * * Remark : in the fractal "literature", addend functions * are not exactly the functions *that compute* the average * sums, but functions *used* when computing those sums.\n * Remark 2 : some sums might not be computable if the number of * iterations (in orbit) is too small (N must be >= size). */ /** * \typedef AddendFunction * \brief Convenient typedef for enum AddendFunction. */ typedef enum e_AddendFunction { AF_TRIANGLEINEQUALITY = 0, AF_CURVATURE, AF_STRIPE } AddendFunction; /** * \var nbAddendFunctions * \brief Number of addend functions. */ extern const uint_fast32_t nbAddendFunctions; /** * \var addendFunctionStr * \brief Strings of addend function enum values. */ extern const char *addendFunctionStr[]; /** * \var addendFunctionDescStr * \brief More descriptive strings for addend functions. */ extern const char *addendFunctionDescStr[]; /** * \fn int GetAddendFunction(AddendFunction *addendFunction, const char *str) * \brief Get addend function from string. * * Function is case insensitive. * Possible strings are : * - "triangleinequality" for triangle inequality * - "curvature" for curvature * - "stripe" for stripe * * \param addendFunction AddendFunction destination. * \param str String specifying addend function. * \return 0 in case of success, 1 in case of failure. */ int GetAddendFunction(AddendFunction *addendFunction, const char *str); /******************AF_TRIANGLEINEQUALITY******************/ #define ENGINE_DECL_VAR_AF_TRIANGLEINEQUALITY(size,fprec) \ FLOATTYPE(fprec) shiftSN_AF[size];\ uint_fast32_t zeros_AF[size];\ uint_fast32_t shiftZeros_AF[size];\ COMPLEX_FLOATTYPE(fprec) prevZP_AF;\ FLOATTYPE(fprec) nPrevZP_AF;\ FLOATTYPE(fprec) mn_AF;\ FLOATTYPE(fprec) Mn_AF;\ FLOATTYPE(fprec) rn_AF;\ FLOATTYPE(fprec) diff_AF;\ FLOATTYPE(fprec) absC_AF;\ FLOATTYPE(fprec) tmp_AF;\ uint_fast32_t currentIndex_AF;\ uint_fast32_t previousIndex_AF; #define ENGINE_INIT_VAR_AF_TRIANGLEINEQUALITY(size,fprec) \ for (uint_fast32_t i = 0; i < size; ++i) {\ initF(fprec,data->shiftSN_AF[i]);\ }\ cinitF(fprec,data->prevZP_AF);\ initF(fprec,data->nPrevZP_AF);\ initF(fprec,data->mn_AF);\ initF(fprec,data->Mn_AF);\ initF(fprec,data->rn_AF);\ initF(fprec,data->diff_AF);\ initF(fprec,data->absC_AF);\ initF(fprec,data->tmp_AF); #define ENGINE_CLEAR_VAR_AF_TRIANGLEINEQUALITY(size,fprec) \ for (uint_fast32_t i = 0; i < size; ++i) {\ clearF(fprec,data->shiftSN_AF[i]);\ }\ cclearF(fprec,data->prevZP_AF);\ clearF(fprec,data->nPrevZP_AF);\ clearF(fprec,data->mn_AF);\ clearF(fprec,data->Mn_AF);\ clearF(fprec,data->rn_AF);\ clearF(fprec,data->diff_AF);\ clearF(fprec,data->absC_AF);\ clearF(fprec,data->tmp_AF); #define LOOP_INIT_AF_TRIANGLEINEQUALITY(size,fprec) \ cfromUiF(fprec, data->prevZP_AF, 0);\ fromUiF(fprec, data->nPrevZP_AF, 0);\ fromUiF(fprec, data->mn_AF, 0);\ fromUiF(fprec, data->Mn_AF, 0);\ fromUiF(fprec, data->rn_AF, 0);\ fromUiF(fprec, data->diff_AF, 0);\ cabsF(fprec,data->absC_AF,data->c);\ data->currentIndex_AF = 0;\ data->previousIndex_AF = size-1;\ for (uint_fast32_t i = 0; i < size; ++i) {\ fromUiF(fprec, data->SN_IM[i], 0);\ data->zeros_AF[i] = 0;\ } #define LOOP_ITERATION_AF_TRIANGLEINEQUALITY(size,fprec) \ {\ uint_fast32_t m = 1;\ if (data->n >= m) {\ csubF(fprec,data->prevZP_AF,data->z,data->c);\ cabsF(fprec,data->nPrevZP_AF,data->prevZP_AF);\ subF(fprec,data->mn_AF,data->nPrevZP_AF,data->absC_AF);\ fabsF(fprec,data->mn_AF,data->mn_AF);\ addF(fprec,data->Mn_AF,data->nPrevZP_AF,data->absC_AF);\ sqrtF(fprec,data->rn_AF,data->normZ);\ subF(fprec,data->diff_AF,data->Mn_AF,data->mn_AF);\ data->zeros_AF[data->currentIndex_AF] = data->zeros_AF[data->previousIndex_AF];\ if (!eq_uiF(fprec,data->diff_AF,0)) {\ /* Avoid division by zero. */\ subF(fprec,data->tmp_AF,data->rn_AF,data->mn_AF);\ divF(fprec,data->tmp_AF,data->tmp_AF,data->diff_AF);\ addF(fprec,data->SN_IM[data->currentIndex_AF],data->SN_IM[data->previousIndex_AF],data->tmp_AF);\ } else {\ assignF(fprec, data->SN_IM[data->currentIndex_AF], data->SN_IM[data->previousIndex_AF]);\ /* Counting zeros in order to divide by*/\ /* the exact number of terms added to SN.*/\ ++data->zeros_AF[data->currentIndex_AF];\ }\ data->previousIndex_AF = data->currentIndex_AF;\ data->currentIndex_AF = (data->currentIndex_AF + 1) % size;\ }\ } #define LOOP_END_AF_TRIANGLEINEQUALITY(size,fprec) \ {\ uint_fast32_t m = 1;\ if (data->n >= m+size-1) {\ for (uint_fast32_t i = 0; i < size; ++i) {\ assignF(fprec, data->shiftSN_AF[i], data->SN_IM[i]);\ data->shiftZeros_AF[i] = data->zeros_AF[i];\ }\ for (uint_fast32_t i = 0; i < size; ++i) {\ data->zeros_AF[i] = data->shiftZeros_AF[(data->previousIndex_AF+size-i) % size];\ if (data->zeros_AF[i] == data->n+1-m-i) {\ fromUiF(fprec, data->SN_IM[i], 0);\ } else {\ div_uiF(fprec, data->SN_IM[i], data->shiftSN_AF[(data->previousIndex_AF+size-i) %\ size], data->n+1-m-i-data->zeros_AF[i]);\ }\ }\ } else {\ /* Result undefined. 0 chosen. */\ for (uint_fast32_t i = 0; i < size; ++i) {\ fromUiF(fprec, data->SN_IM[i], 0);\ }\ }\ } /*********************************************************/ /***********************AF_CURVATURE**********************/ #define ENGINE_DECL_VAR_AF_CURVATURE(size,fprec) \ FLOATTYPE(fprec) shiftSN_AF[size];\ uint_fast32_t zeros_AF[size];\ uint_fast32_t shiftZeros_AF[size];\ COMPLEX_FLOATTYPE(fprec) znm1_AF;\ COMPLEX_FLOATTYPE(fprec) znm2_AF;\ COMPLEX_FLOATTYPE(fprec) diff_AF;\ COMPLEX_FLOATTYPE(fprec) ctmp_AF;\ FLOATTYPE(fprec) tmp_AF;\ uint_fast32_t currentIndex_AF;\ uint_fast32_t previousIndex_AF; #define ENGINE_INIT_VAR_AF_CURVATURE(size,fprec) \ for (uint_fast32_t i = 0; i < size; ++i) {\ initF(fprec, data->shiftSN_AF[i]);\ }\ cinitF(fprec, data->znm1_AF);\ cinitF(fprec, data->znm2_AF);\ cinitF(fprec, data->diff_AF);\ cinitF(fprec, data->ctmp_AF);\ initF(fprec, data->tmp_AF); #define ENGINE_CLEAR_VAR_AF_CURVATURE(size,fprec) \ cclearF(fprec, data->znm1_AF);\ cclearF(fprec, data->znm2_AF);\ cclearF(fprec, data->diff_AF);\ cclearF(fprec, data->ctmp_AF);\ clearF(fprec, data->tmp_AF);\ for (uint_fast32_t i = 0; i < size; ++i) {\ clearF(fprec, data->shiftSN_AF[i]);\ } #define LOOP_INIT_AF_CURVATURE(size,fprec) \ cfromUiF(fprec, data->znm1_AF, 0);\ cfromUiF(fprec, data->znm2_AF, 0);\ cfromUiF(fprec, data->diff_AF, 0);\ data->currentIndex_AF = 0;\ data->previousIndex_AF = size-1;\ for (uint_fast32_t i = 0; i < size; ++i) {\ fromUiF(fprec, data->SN_IM[i], 0);\ data->zeros_AF[i] = 0;\ } #define LOOP_ITERATION_AF_CURVATURE(size,fprec) \ {\ uint_fast32_t m = 1;\ if (data->n >= m+1) {\ csubF(fprec,data->diff_AF,data->znm1_AF,data->znm2_AF);\ data->zeros_AF[data->currentIndex_AF] = data->zeros_AF[data->previousIndex_AF];\ if (!ceq_siF(fprec,data->diff_AF,0)) {\ /* Avoid division by zero. */\ csubF(fprec,data->ctmp_AF,data->z,data->znm1_AF);\ cdivF(fprec,data->ctmp_AF,data->ctmp_AF,data->diff_AF);\ cargF(fprec,data->tmp_AF,data->ctmp_AF);\ fabsF(fprec,data->tmp_AF,data->tmp_AF);\ addF(fprec,data->SN_IM[data->currentIndex_AF],data->SN_IM[data->previousIndex_AF],data->tmp_AF);\ } else {\ assignF(fprec,data->SN_IM[data->currentIndex_AF],data->SN_IM[data->previousIndex_AF]);\ /* Counting zeros in order to divide by*/\ /* the exact number of terms added to SN.*/\ ++data->zeros_AF[data->currentIndex_AF];\ }\ data->previousIndex_AF = data->currentIndex_AF;\ data->currentIndex_AF = (data->currentIndex_AF + 1) % size;\ }\ cassignF(fprec, data->znm2_AF, data->znm1_AF);\ cassignF(fprec, data->znm1_AF, data->z);\ } #define LOOP_END_AF_CURVATURE(size,fprec) \ {\ uint_fast32_t m = 1;\ if (data->n >= m+size) {\ for (uint_fast32_t i = 0; i < size; ++i) {\ assignF(fprec, data->shiftSN_AF[i], data->SN_IM[i]);\ data->shiftZeros_AF[i] = data->zeros_AF[i];\ }\ for (uint_fast32_t i = 0; i < size; ++i) {\ data->zeros_AF[i] = data->shiftZeros_AF[(data->previousIndex_AF+size-i) % size];\ if (data->zeros_AF[i] == data->n-m-i) {\ fromUiF(fprec, data->SN_IM[i], 0);\ } else {\ div_uiF(fprec, data->SN_IM[i], data->shiftSN_AF[(data->previousIndex_AF+size-i) %\ size], data->n-m-i-data->zeros_AF[i]);\ }\ }\ } else {\ /* Result undefined. 0 chosen. */\ for (uint_fast32_t i = 0; i < size; ++i) {\ fromUiF(fprec, data->SN_IM[i], 0);\ }\ }\ } /*********************************************************/ /************************AF_STRIPE************************/ #define ENGINE_DECL_VAR_AF_STRIPE(size,fprec) \ uint_fast32_t currentIndex_AF ;\ uint_fast32_t previousIndex_AF;\ FLOATTYPE(fprec) tmp_AF ;\ FLOATTYPE(fprec) shiftSN_AF[size]; #define ENGINE_INIT_VAR_AF_STRIPE(size,fprec) \ initF(fprec, data->tmp_AF);\ for (uint_fast32_t i = 0; i < size; ++i) {\ initF(fprec, data->shiftSN_AF[i]);\ } #define ENGINE_CLEAR_VAR_AF_STRIPE(size,fprec) \ clearF(fprec,data->tmp_AF);\ for (uint_fast32_t i = 0; i < size; ++i) {\ clearF(fprec, data->shiftSN_AF[i]);\ } #define LOOP_INIT_AF_STRIPE(size,fprec) \ data->currentIndex_AF = 0;\ data->previousIndex_AF = size-1;\ for (uint_fast32_t i = 0; i < size; ++i) {\ fromUiF(fprec, data->SN_IM[i], 0);\ } #define LOOP_ITERATION_AF_STRIPE(size,fprec) \ {\ uint_fast32_t m = 1;\ if (data->n >= m) {\ cargF(fprec,data->tmp_AF,data->z);\ mul_dF(fprec,data->tmp_AF,data->tmp_AF,render->stripeDensity);\ sinF(fprec,data->tmp_AF,data->tmp_AF);\ add_uiF(fprec,data->tmp_AF,data->tmp_AF,1);\ addF(fprec,data->SN_IM[data->currentIndex_AF],data->SN_IM[data->previousIndex_AF],data->tmp_AF);\ data->previousIndex_AF = data->currentIndex_AF;\ data->currentIndex_AF = (data->currentIndex_AF + 1) % size;\ }\ } #define LOOP_END_AF_STRIPE(size,fprec) \ {\ uint_fast32_t m = 1;\ if (data->n >= m+size-1) {\ for (uint_fast32_t i = 0; i < size; ++i) {\ assignF(fprec, data->shiftSN_AF[i], data->SN_IM[i]);\ }\ for (uint_fast32_t i = 0; i < size; ++i) {\ div_uiF(fprec, data->SN_IM[i], data->shiftSN_AF[(data->previousIndex_AF+size-i) %\ size], 2*(data->n+1-m-i));\ }\ } else {\ /* Result undefined. 0 chosen. */\ for (uint_fast32_t i = 0; i < size; ++i) {\ fromUiF(fprec, data->SN_IM[i], 0);\ }\ }\ } /*********************************************************/ #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/examples/fractal_files/000775 001750 001750 00000000000 13175112471 020223 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/examples/config_files/config18.config000664 001750 001750 00000000262 13175112471 022661 0ustar00mpegmpeg000000 000000 C075 JULIA 0.28294016280463 -0.016304694643679 0.0 0.0 3. 3. 16.0 1000 1 0x0 ITERATIONCOUNT SMOOTH IDENTITY 3.0E-2 0 0 0x39A0 0.25 0xFFFFFF 0.5 0xFFFE43 0.75 0xBF0800 1 0x39A0 fractalnow-0.8.2/examples/config_files/config07.config000664 001750 001750 00000000303 13175112471 022653 0ustar00mpegmpeg000000 000000 c075 julia -0.4 0.6 0 0 3.15902076051223 3.15902076051223 1000000 1000 1 0x0 averagecoloring triangleinequality linear identity 1.875 0 0 0x39a0 0.25 0xffffff 0.5 0xfffe43 0.75 0xbf0800 1 0x39a0 fractalnow-0.8.2/examples/rendering_files/render04b.render000664 001750 001750 00000000120 13175112471 023543 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING STRIPE 1 NONE CUBE 1 0 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/examples/config_files/config14.config000664 001750 001750 00000000221 13175112471 022650 0ustar00mpegmpeg000000 000000 c075 julia 0.5 0.25 0 0 2.57775119617225 2.57775119617225 1E+20 100 1 0x0 averagecoloring stripe 1 spline cube 1 0 0 0xffffff 0.5 0x0 1 0xffffff fractalnow-0.8.2/gui/src/gradient_dialog.cpp000664 001750 001750 00000004364 13175125232 021010 0ustar00mpegmpeg000000 000000 /* * gradient_dialog.cpp -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ #include "gradient_dialog.h" #include #include #include GradientDialog::GradientDialog(const QGradientStops &gradientStops, QWidget *parent, Qt::WindowFlags f) : QDialog(parent,f) { setWindowTitle(tr("Edit gradient")); this->gradientStops = gradientStops; gradientEditor = new GradientEditor; gradientEditor->blockSignals(true); connect(gradientEditor, SIGNAL(gradientStopsChanged(const QGradientStops&)), this, SLOT(onGradientStopsChanged(const QGradientStops&))); QDialogButtonBox *dialogButtonBox = new QDialogButtonBox(this); QPushButton *cancelButton = dialogButtonBox->addButton(QDialogButtonBox::Cancel); connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); QPushButton *OkButton = dialogButtonBox->addButton(QDialogButtonBox::Ok); connect(OkButton, SIGNAL(clicked()), this, SLOT(accept())); QVBoxLayout *vBoxLayout = new QVBoxLayout; vBoxLayout->addWidget(gradientEditor); vBoxLayout->addWidget(dialogButtonBox); setLayout(vBoxLayout); QTimer::singleShot(5, this, SLOT(initGradientEditor())); } const QGradientStops &GradientDialog::currentGradientStops() const { return gradientStops; } void GradientDialog::onGradientStopsChanged(const QGradientStops &gradientStops) { this->gradientStops = gradientStops; } void GradientDialog::initGradientEditor() { gradientEditor->setGradientStops(gradientStops); gradientEditor->blockSignals(false); } fractalnow-0.8.2/gui/icons/icon22x22.png000664 001750 001750 00000002655 13175112471 017654 0ustar00mpegmpeg000000 000000 PNG  IHDRĴl;gAMA asRGB cHRMz&u0`:pQ<bKGDC pHYs   vpAgXIDAT8˅]UU}=Ϲs8㈄)D& RS=E$VCSHCVE%PHAf(33:s̝;|֝11foZ[8|$P\Z-[{ ` XdEC*qLN}M1p*iNy  ǁ5kqpzi PRI@{=PQ,^.'(c ƭ3ŢqVS6FB Q,1j:r9Cg,7J(%J-KnP߇lVm[Q(@1< cc1C$CLOPIڢRpURr[RP,&TFbJ >> SU Μ'Z"cď?]m5':K%(AyFG_7^@W(XFkI1]FGcl̐ɴ4G L.]'Ȯ.zk+ jRw+޽Edy.6,LLQ.fxM0W#C9sYME Zh@u[d+.q~yNٰyIEc@g2NG ݪUEXUEˋkXՏo;: lV@!bnC DE1T*P}cG[\NޱoؾcZzݢՂ~_8m:>cD_ڊe)Q:w?4_3LMUy!v櫰 yHnKEZ-9σ) ݶc[yI2=h6! ݮ @'P0#hYKK"IAhc3{9c+7zn H^:U * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file uirectangle.h * \brief Header file related to UIUIRectangle structure. * \author Marc Pegon */ #ifndef __UIRECTANGLE_H__ #define __UIRECTANGLE_H__ #include #ifdef __cplusplus extern "C" { #endif /** * \struct UIRectangle * \brief Simple rectangle structure made of unsigned integers. */ /** * \typedef UIRectangle * \brief Convenient typedef for struct UIRectangle. */ typedef struct UIRectangle { uint_fast32_t x1; /*!< X coordinate of the rectangle's top left corner.*/ uint_fast32_t y1; /*!< Y coordinate of the rectangle's top left corner.*/ uint_fast32_t x2; /*!< X coordinate of the rectangle's bottom right corner.*/ uint_fast32_t y2; /*!< Y coordinate of the rectangle's bottom right corner.*/ } UIRectangle; /** * \fn void InitUIRectangle(UIRectangle *rectangle, uint_fast32_t x1, uint_fast32_t y1, uint_fast32_t x2, uint_fast32_t y2) * \brief Initialize rectangle. * * x1 must be less than x2 and y1 must be less than y2 * (undefined behaviour otherwise). * * \param rectangle Pointer to rectangle structure to initialize. * \param x1 X coordinate of the rectangle's top left corner. * \param y1 Y coordinate of the rectangle's top left corner. * \param x2 X coordinate of the rectangle's bottom right corner. * \param y2 Y coordinate of the rectangle's bottom right corner. */ void InitUIRectangle(UIRectangle *rectangle, uint_fast32_t x1, uint_fast32_t y1, uint_fast32_t x2, uint_fast32_t y2); /** * \fn UIRectangle CopyUIRectangle(const UIRectangle *rectangle) * \brief Copy rectangle. * * \param rectangle Pointer to rectangle to copy. * \return Copy of rectangle. */ UIRectangle CopyUIRectangle(const UIRectangle *rectangle); /** * \fn int CutUIRectangleInHalf(UIRectangle rectangle, UIRectangle *out1, UIRectangle *out2) * \brief Cut rectangle in half. * * Cut rectangle into two rectangles.\n * If the rectangle cannot be cut in half, out1 and out2 will be left unchanged. * * \param rectangle Rectangle to be cut in half (will not be modified). * \param out1 Pointer to put the first half of the cut rectangle. * \param out2 Pointer to put the second half of the cut rectangle. * \return 1 if rectangle cannot be cut in half, 0 otherwise. */ int CutUIRectangleInHalf(UIRectangle rectangle, UIRectangle *out1, UIRectangle *out2); /** * \fn void CutUIRectangleMaxSize(UIRectangle src, uint_fast32_t size, UIRectangle **out, uint_fast32_t *out_size) * \brief Cut rectangle into smaller rectangles. * * Cut rectangle into smaller rectangles. Each of these rectangles is smaller * (i.e. both width and height) than given size. * * \param src Rectangle to be cut into smaller rectangles. * \param size Maximum size of the small rectangles produced. * \param out Pointer to a (not yet allocated) array of rectangles for the output. * \param out_size Pointer to an integer to store the number of small rectangles produced. */ void CutUIRectangleMaxSize(UIRectangle src, uint_fast32_t size, UIRectangle **out, uint_fast32_t *out_size); /** * \fn int CutUIRectangleInN(UIRectangle rectangle, uint_fast32_t N, UIRectangle *out) * \brief Cut rectangle in N parts. * * Cut rectangle into N rectangles.\n * If the rectangle cannot be cut in N, the out array will be left unchanged. * * \param rectangle Rectangle to be cut in N. * \param N Rectangle is to be cut in N rectangles. * \param out Pointer to the (allocated) array in which to put the N cut rectangles. * \return 1 if rectangle cannot be cut in N, 0 otherwise. */ int CutUIRectangleInN(UIRectangle rectangle, uint_fast32_t N, UIRectangle *out); #ifdef __cplusplus } #endif #endif fractalnow-0.8.2/gui/icons/icon36x36.png000664 001750 001750 00000005437 13175112471 017667 0ustar00mpegmpeg000000 000000 PNG  IHDR$$gAMA asRGB cHRMz&u0`:pQ<bKGDC pHYs   vpAg$$x IDATXÍ[\Uk_g칝k)--HAJZµ1"RH|ACL5A!>(B jD (4@QH9==meϾ,Y3lw2뿾K=x~{mocY`PiCE`pxԔ7e80=Ih6<)p( o)ջRJ&9|۶,hY^(%sM`s`84i,dFl-SvSCGtOS fS*tdضE܊Y8ޥQ?>?sb㚫k7-Ęw% R&`AQd+ ߷V-J6o͵_a=^9SZS\"v$OSmZ㺚ZmT\[-5n?|_bg8B##b* (۹/Q\c/oSǽ|kͭ,Q^On3@\e|2R' XK3J$F9P< G/#]IP騱P C0:0uTܢ9sFnBncPS ۞?GJwB|8L,kf8 i[69Bݮwgy.bDדwgD:nk6+NB2c|8 `}T3JY&Xݖh734''JIot: 2Y&Z|@I*%4`rߤ Rc)n@Ʊ3ժ~ZX^V"3l2hv^2פe ѭ?e"M(9QN^;Mydra%tEXtdate:create2012-05-27T10:48:29+02:00+b%tEXtdate:modify2012-05-27T10:48:29+02:00qIENDB`fractalnow-0.8.2/examples/rendering_files/render02d.render000664 001750 001750 00000000134 13175112471 023550 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING TRIANGLEINEQUALITY SPLINE CUBE 1 0 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/gui/include/gradient_label.h000664 001750 001750 00000002444 13175112471 021127 0ustar00mpegmpeg000000 000000 /* * gradient_label.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file gradient_label.h * \brief Header file introducing ColorButton class. * * \author Marc Pegon */ #ifndef _GRADIENT_LABEL__H__ #define _GRADIENT_LABEL__H__ #include #include class GradientLabel : public QLabel { public: GradientLabel(QWidget *parent = 0); private: void paintEvent(QPaintEvent *event); QGradientStops gradientStops; public slots: void setGradientStops(const QGradientStops &gradientStops); }; #endif fractalnow-0.8.2/Makefile.configure000664 001750 001750 00000002330 13175115345 017230 0ustar00mpegmpeg000000 000000 DEL_FILE = rm -f CHK_DIR_EXISTS= test -d MKDIR = mkdir -p COPY = cp -fp COPY_FILE = $(COPY) COPY_DIR = $(COPY) -r INSTALL_FILE = install -m 644 -p INSTALL_PROGRAM = install -m 755 -p STRIP_BINARY = strip --remove-section=.comment --remove-section=.note INSTALL_DIR = $(COPY_DIR) DEL_FILE = rm -f SYMLINK = ln -f -s DEL_EMPTY_DIR = rmdir --ignore-fail-on-non-empty DEL_DIR = rm -rf MOVE = mv -f CHK_DIR_EXISTS= test -d MKDIR = mkdir -p all: $(call quiet-command,make -C ${LIB_DIR},"") $(call quiet-command,make -C ${COMMAND_LINE_DIR},"") $(call quiet-command,make -C ${GUI_DIR},"") %: $(call quiet-command,make -C ${LIB_DIR} $@,"") $(call quiet-command,make -C ${COMMAND_LINE_DIR} $@,"") $(call quiet-command,make -C ${GUI_DIR} $@,"") Makefile: configure Makefile.configure ${LIB_DIR}/Makefile.configure ${COMMAND_LINE_DIR}/Makefile.configure ${GUI_DIR}/${GUI_PRO_FILE}.configure ./config.status distclean: clean make -C ${COMMAND_LINE_DIR} $@ make -C ${LIB_DIR} $@ make -C ${GUI_DIR} $@ $(DEL_FILE) "${LIB_DIR}/Makefile" $(DEL_FILE) "${COMMAND_LINE_DIR}/Makefile" $(DEL_FILE) "${GUI_DIR}/${GUI_NAME}.pro" $(DEL_FILE) Makefile $(DEL_FILE) config.status fractalnow-0.8.2/examples/rendering_files/render01c.render000664 001750 001750 00000000135 13175112471 023547 0ustar00mpegmpeg000000 000000 R075 1 0x0 AVERAGECOLORING TRIANGLEINEQUALITY LINEAR LOG 6.3 0 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/gui/qfractalnow.qrc000664 001750 001750 00000000740 13175112471 017424 0ustar00mpegmpeg000000 000000 icons/icon16x16.png icons/icon22x22.png icons/icon24x24.png icons/icon32x32.png icons/icon36x36.png icons/icon48x48.png icons/icon64x64.png icons/icon72x72.png icons/icon96x96.png icons/icon128x128.png icons/icon192x192.png icons/icon256x256.png fractalnow-0.8.2/examples/rendering_files/render03a.render000664 001750 001750 00000000116 13175112471 023546 0ustar00mpegmpeg000000 000000 R075 1 0x0 ITERATIONCOUNT SMOOTH LOG 2.5E-1 0.5 0 0xFFFFFF 0.5 0x0 1 0xFFFFFF fractalnow-0.8.2/examples/gradient_files/000775 001750 001750 00000000000 13175112471 020404 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/gui/icons/icon64x64.png000664 001750 001750 00000015343 13175112471 017666 0ustar00mpegmpeg000000 000000 PNG  IHDR@@iqgAMA asRGB cHRMz&u0`:pQ<bKGDC pHYs   vpAg@@`IDATxڭi%u{2o 9% iD I)F1QCVȀX1% 8"o@^"KIX ,SVb$E2X2g{*έMl-9?KO}T|q8P /8q]t2 `>cgϹ.<$$t Y&7u! 1Cx )NJX߾Ok Pw|.x榢'ne)7 mHCj!~+@;t (Y<p]yWʂ<;%3c0ϓ՞$cpz9eK~]+q8βM7==4} QJ}ymvdZ\W}垦+0DZhb6:om]}Z|YZ7982Wsh'0$acC$oqEu@BZ{Q(RjTqC'sc~vlEGICaMpTV}_x,`$2/+"EVX֮[-(ZՓDƆf4r0FẊy. !z0Wm.ͯ~~̓͹Stf?M}E͑<Ȳ:Cp]xeo[gY h-(,Te5sCS(Xr]E -A9$Ie( KwyE3.GDa:1DzplLDQ$18 U\&5˒77k]#G4өQZ놲8(Gښ҄a΀ & ;}xa0@m Dl8+D[a&DpXSzFk^kŦ7z"4}UUߧ5;x-ܚʊ0@ 2Zy[eҴOt6.EnzU`xӱoe>zU\Hy7}I,W F#e6j<+!P\LﲳYPgy.Ttz N &Ƴ |W!/^0Bh?"G|!'O]ُ]SnN睌FN\,,r:.fbnSG%Y/lծ”˜gc.g*_SUNGņ:4M?Z5#1u͵J-*)KE]2(" E08Cc_G[\h8$p~v;*70)wTXL2WcX]U 4UL&^O")*][.aI0J ?͟~)>lM?ːg.M|iC%|N奄YYb|%pK1ErU!:Z+tJ<:(OදCyG@]e2ܣ9IZow]Vm[y&:0{DYQ`Y yi ^x幪bf)7 [_vIjpR{wQAޠ3_ak6cZ|%/M迺=Svxq}١ LDW *Mx8+K!2q\'!mр {5QxeRcMٝ 0Q}Nݧ\~9~Dtoo;=t![qtcI^F0 ¬"c>O~p!N,>o|kU\Z_̧Ώo^lĜ (GB|_9FZ}_b~c ݮ!IRx 120}/.;{тI3ɜZsG!nzeL+LUMx ^&m# Gt!ċ#'o" <M=җ/swōf-?| AGrWU HRT$wmj56ߨ#Z{ ^)k=dU233|As~'} ;js{be`ZgSYV蚵@T3[gxa*Nr?7]nuؚ͘9A̽Ov| 5w/ o/Z*T6^i xөݬ6>fm5|DJc2ϝA#Cq7pkp?|׷g'}z=Fq|,/=Tx>_Nj-j]gjs1^yÉōgWw9zy"VЭw\;4}sأx'"M=qj-Vhm' L?K_8BES-ֆ,q]o4aqn;OG>3x85^1ڒ;^뼀g{@R]#{(d}8_=z8N"!&@@s`[6G5W_GXP=~f4]wRlYKnKl4TchwWEy3Q\xp |p;}gKw4:yt8EV\GEFGr66lDhuE1Eu@\-phMcdO?-7Fv/ЍPiQ<;B;:r'7BN<yuqܫy &fcĆRĵiFaNG;myieR$]N%̂WK9LE΢nZPuDsoCg}c_ #O\&N>8~}P̮nFixifF#gՂ.lbs5P& CCURo'f|C6I뽄+);ǘ5!hO?O^|P:w9q; W( $-o dS\,uv`_q*?]W-%9j}_T Yu1FAkׅ<H$YEO\~߬ijs>rәCr200ٌ54mx\8(;ЗFiXn]eIh8a{[\t0 l!n[3c79Ȕ|3ɉ,d<DF#RXdB`UeOHo*۪jm=x’#kFV@b6NcyVذֈ{@G.rt J䄈HVx@ݚ#RJm_69){ oo ˢ7 BD I"&ٍPH GPń:ex첻kl랩k( gi#U0$`(KLJdE-Aٖ6+#,x\7e *'(n|<0 LA -a](xI$F^` C*^qiM%`vln|en]:U"Zuf_UV`g;>Z"w'lP%eRG ]J-$Z(],ssMo,K^ݶAg?uwuvx_UHӇ6MZtȯhk Ht aqCqDYMijg\TPx֭9XUfdg|`5Xs>MjVsf({=z~9ṛ^\,?xx=cdM._y.Z`ݬq׌]=>YUuet*yb mtjqװۣ6wgﱋjFJSX_{^_:4]ЋhBy/)ť>;D&p%tEXtdate:create2012-05-27T10:48:29+02:00+b%tEXtdate:modify2012-05-27T10:48:29+02:00qIENDB`fractalnow-0.8.2/gui/icons/icon128x128.png000664 001750 001750 00000051203 13175112471 020023 0ustar00mpegmpeg000000 000000 PNG  IHDR>agAMA asRGB cHRMz&u0`:pQ<bKGDC pHYs   vpAg01QcIDATxweu9~u zBQER$%M)ٲe˖%KN8XYL%DzgE^wQe/( p 0W_?ẁ"ܵ~kf~ʽwކ,Yky7NcxGFc=А`|-1{ϓ?}_~:K > w<x,4}0˟e^ɚ-iZ,am{bxAc,O=}_af Qw8e1f7Ysk}9pO$z(~eB {;,Y&h᫗nBiwGKR\牰$8.5=:_2ӔO? C~676F#8.mXnj7L $8bF#S,+ {%a6Ir7] n"@ͫ3ܸq?j19ͦѠ0zW^]ǣTXe7I; I" wJnrf,UAPLϓje @+ ~j6e%'QTiw7S??IįfdHl\*(ql"PZHSáC,mۼ5a-LCDOO}{-՟ZȂ=VaX-9_:X+6jBhi"h,IbeiZM~FPF{=q窖]tErQ5X&i0ٌ0佁1<h! *jlm땺XEUNx8)i:Y=qCрT`O=uQө)E4f|$ڦVAe]00uEgO%ON< D j8_rYB(&½\gGe'ʮuPMMKSWUro^G)Q5n^@ng۰1wM_]$^ٚM?&Sja>K-Nc冡z` ˑ#vw VקEΓv0̇Us[jґZ,yw] UoG*Gj)t j5y]\S(Pj9 !^V͛~^&B5*s吜8Egry_, 4Ko3tMh$bT8m"I7A`usntyגaT-ErThf@,G\{yx|f8,1eI9 3lo#7QLym @5RF\^tvz]AN emMld8>(H6 @, 5O!B((ͨh᰼w5-ZG-\n[x,I'[8z@4* n>z63lmɉt,~<6׎/E6 3P۵y>gUm1F؆ . HiN?MKMRdNuI"1v'T{$)bj.\PFxl CpO\/BԟacC,vm-eEҮqZM] W@:;˄M:dۛlJ /g3ūJD0H4nlfm%\!g"FubP h*` Ff{p5i*ٔ՛QUhLF"d,E*F۫}k.,-0.CGOQ$w0{ qhӲzQ8s9<@DUVDlmv-ɮ)N^+ &j'5q, k-AáaoO$NV7Ea]c=3y$)*P 84{<ɿ]9jQ0K45`鳌*PP˳4a4:PNY6yPwgk$Qk[̠pQ[l昀k9dX f1O`HW-:z)((|Fke21j9Qdsa0sv KR/(EP5ZN kk}#trAX0E؈w:n6Kah{>:޷t ;;Ѩ̇C|pN=XbztA%!D6;;A~2Mpȗ)§9gq,R<а!_ R$[{-/=ыdTJ2\86++@]n.Ap' !gsy&Zc6U3PKo洂+Q$kHz]NK,*IH6U)&߸<z>Q$Bj^/f7wh3ԬB<_Wa)rjo6?H:^.ٴy$!$ԜL[x^N^QԦ鐦>q쑤4u ^qb"J>`A" Ⱦ\,S𘅛\՘Ճ8X89d x<6TN&4áa0]-gx"Ymjjù=4YJϬGoWtE"zZ{5i8'ܡuNڈzmLxg4=zĹy4f']w7WIL$_6Y4f Ӥ?ıe}] eVD-<8+W_T{&HSFtꑦHZ-%<3,^С.~ yމa=hih$ɥf3˝fPz$Pqm)=$騗r(n,rҔqt-ȈLٱZ]27IT|]Kkszk=( ;JC~W~ނz#?^$)nwzFjj)8~c+~*/ѫMo)b uO Sf2QDM/X݃8lQ r D;E \PS,#*]!o[/sG_N0\*( t:$d59i Ǣ]"kdgg91kiTWK<=e}ԭJhWzU\\%1E*g3Y8♢STt2d;IB>f9ߕMcf;1)wQZb̓{W/_Gj>yj#IL6jՃaw°\~6Wue & 6M72"K5^`z{{z)PZz&*iWDUi1BpJ0yez)өHs.Ę60xq^*Ws_޽gh|p?I6[~!i-F#f8{IZxc-BF5D@]*X ]&Vҩ)Ҭ^rmYY}mCnT2'?qjeעMZ5 a<Ŷ xA_>bӼ4n/ _*_C(_ݹE}}CBMA"Qbt[w6Pz% Z$("Qө`++q W`%-ڮeDYfN= y)ƌMOToam_C0yGfLYޖd؍2'`.x"gL03!IܠՄ3]lNz$rq:5eJ=]l.FYF2+W!rU8G#W T;vQ455ߟ=QL0г}#:r96{ Wk|;VȀ]S&8~ 6 HfD ג$yUIUc/JAdT ]-gI-J% IDda%݅O"V+O!=jQ AG̮|q.[?ѸXӧ)[4dL[D7gm*/Qx_ٔn kNGV`ۀ0ʅml yz "X \/ȟHSTYϳWU21M̟ nHY4+W4u /ɓ4WNvw IZIX*1`O$3f/>?ƥ:l̡8„to*7lNؿ%;7]gٺ+kֹ_⯏gɺɟȯvxٓP퓜 Ҫkqhd} iZcgϛtIw۹ZHnsX,xiEaxj8{$|Ɩcʅ!5*$ᳲ"BD=xeiL}DBJ5? bj̧ݎ>Mis3~wqc}pF_O^Ӳ|y4cg6$bR_<<҉491}OpQ_btG&Qxl?d}o}zHOӈױIb-`ok h,^|׶/v ;;Dm:Hs{TXDItٻz 5LE%"i3 Z-?t& qJ1&MM/e]gy唿cp>y-|`̣cUw$#9K|Q#/w͆#e>t̥l_6Θ82M/븒,fg 3_XGy9f]FAl?+ۥ+ UYCTkp+1ɩ%>/hԼ#h!vղ:;d }Vи$1L&h{5ur`ǺלJL"7h&$? ȰY3_=Ɠ{L67 WWï Cz}|'y8rz3^4SV>R"XBqI(ON>}/uG;K|c, W;Z]kD*LF# a0 rÒ)'\I!ڸ\ASVKԹ7v1WRUc -[-ext#`L Ȳ(0&CfgAYN!Ah[Y|ߌϴMCVxB{/aoյ7o_d+'kFBF^sOKvWk ]>%ըdI֮r1fN\Rex@Pܘ,N'^;<.A`)y?3S``XYX]/2oy`|w55@,رd- jBv &CE<1q[{WēljMy"d༥d9Z7!<+C͌P[\\yJu8 A*PVkUF/N=$$3RcOsl(tl3$<̧^LVM b )0M6=W?,?ri8?`N/;'F%~}}!ڷ1GxJuivn3pi% 4&@ks3.em|6mT_!ĻW҃bVFxyj3J 0Na;;lxM`caѸd.Vo`m c^|#\޵4r?G|=6#n]d16T tWV&yhJ^s-.f4T\մJDNwo 9m%n (aT5HiM/}~z#G`:?%:tG3v{Os]{xU/hx'^t$<,=`G=_:}WfۏwyE{V!NIOi'oMLqX>6cpښ-)Ei:E2y++^Mwpmo%;Wy엏1L6M_;q*"|76S/qԘKtGԢ0t 7po ;Xj{(~kmDwba7&9l.*lnLєZ[Dj[.ճR^]#]hZclBF)ǽ\Je> ]3;lv{t~|ngh q}ϷyƋ\ws 6Γn]C>w9/z^g2vf5MY03 )#}8{ }}$i{Kl G_H_h0'd6VjuH/s /X[]%)_~|C>'IB}?o5[ 0xdY]D7; ,jq@pz=_P hWn1 HԎbeE˖4 ݞ>A0Ƥ`G6pWۦ{ wF}If y< >'_^/̟G\9ƋYUzm'ohېIf9Jj&jJl3\(5EVUG3ݮ-byv;#Mȟ:Y]MNL___+[Sn|ҋ|] y~E~#ieO? mrϛXYie\ gʉP]mQP@a Th_G;T#(v:)i@&BLB)U7O3]C&agi{l<;^=1 /򷷾gD^ݗŏ;t?6IS(`4*ky;qn{$1ƍ'Bbi[[꽽Ոn/[Y~+@kc0Z||~S -K}|nWޠlcc=ztF2lc A{g><3_>Kgfl,ǦհKS<O6IbQI:Kr5I.í/'~֎%-| Ø0F>ah.:V~tt3xWa(Y}-7j3i gx?k\A`<0xɧz߹Z0UHСښzF 6dN` Ŧ/&G|]݇0}f>/N_1s!G^N/=*zg=7GH.a``/qJ0"ǿze kMK`Yn |̀ )Q3o4^;5 sܒ L¬tp7OFu\O=l7aq7bG}^zMgX] vcEli©C MʖE_lu%Wz27e)vENrңT$I筒eGA6 D@hai5#Bo=oL{>>Sgw;p6߉c0|uǁ͸pảڌ9I<1!hg3ieO͔m]{p8627ЭuAvư !MDL&>FC2fZ?ZxcV pqB6KcX@݋1)_uf{O?CԽөtEDFQe߇CSD9$}A4I)*H䕪C tptj _S Ì8ț/{~ 4mO8ZǫkУS?gW ێmcy|20.e{ǧupkhl܂ͼ&sRS"vJ~n㱻+n4lކE4P9z9`vF `60'<Ò 0$/|GNqא u;,7?|%m9 ?}Aϧ7n8ڻ0цB7zߎȾ + .'lwq>ԣV3Z rR-:NzNz.h-;jmMHzDi-r7 `qzXt& S`Al|>ӿOr{lI wq>{Vs@z3.X0zsbf`̴Ry,g84yQл ,3t#0|pYw) &O¡CLYgwhN NٔpeIr/٪P`x3s{NݳEطՎ1zOvq}[p7+݋k<0!+l^s yfcKhkb#L{X?&xdWlqTCuSz9LTpn*]^'kw:#\0̐eYVmGk&'͕aX5F' ?xˀcgΧ|FukEyMI8&\#׊pfȠ;oYoU F'e)>IO:ʇTqWZG)}kLAT!lW' 9PdLD}hDZ0K N.Z?v8=<ə?&QZ?^MߙquG&Q-EQhyn4l^(b?l\g@:tܔ@Kh9Q\g<^.{kn!IL1r6a !e<N\(2 Bh>Q]n('4?{oxo+oB $ik]ҍV؟ x ܱOs]gnC|%^3N.ػ %L>[@ښ-SrJ%9);wTnR&tqUFT'}\[+)*<:QLTW9mhkcfe7455r2vk[&x.ͣkY z'K[x(䞖׾:&K-;iYL4D`4%C:Q#5^ï=ޥm~SSw8Byh]$ZGhI21#U5b]SmA>4JH_|͛{VE@^%辶]a)_it͍ޤ 'ARv$NcQs9||\z}>׽qFmò~, hY<_}Qn<ٗ y+Wlu˻?q>FZ®s?i3'+`7a1/1K^kW$50BT}9YC ńFllHz>Є|r4A'$6*09ܱ&9FP/tC-aN|( .i3ol$Wx^;8ZVpS]~밶˴GpƍoݢV=ſ&O?W{ųiVOg>]LG';Ism7Kr#h\c6ᅪl0&MV rWV 0| sDOݻ~8ܗNWV64!rï_Sƪ>  ~ . %M(Rb4&$.:eP$K9T4s<4H5x+2=ϑwŋVU)oC'> v8sN87~zTorקomq?p Xs\/c+`4fk ӹ8)hV2uv*T[Y tZ&W bT5 (}xl2WfZkqag8cY޿+}nl)[Qd C*!:A-GSL5m!PffcBvXv]⑏޷zݳG1fⶫX1S-zxBv͟LL5|?&I' Yfo+ &zdjʭ0 ܓW=WeBLc갈ԗQ[YELJ Yu00EQ?Ca6*yrsФa4 rML`ӟg심wϜ^?hBf9L+QkA 2捧KdJXH">p5 sT0reo+gv.eQLRdH alXмi=1/i V!_h$m& Hc2\Wk/ץeO$/ . ȲQsZV$r2Z[L񔹃)Уq{3u76ĉ BmFCSС\ 8MuF'=bI)(^Ϥ[E6L/L}_"mX|c4N|u2"jl1Lۊ_`A|/EϫA E+H3vm-2DjQܠEseEr+?U .gA+VVŬ{{~gkxf &]dtzwSge^(6G$X[ː%o-K@az2@Zrz%glSMp x+@UTCWW %`T˽^a\ji2ў~+ ("kkX[K iϐ?ɹO}c5> }=iLSMSfSQ{/@Ϭ}Ei861wm2a4f r)aِ@QrJ+y@-ed\0CĀnmE+2ʮ<.-~:[dśΐJ$jexdɀ8?&x#pK]&e82U2:hHek Hӑͦl@̽|ׁvZSV/M1W{6=lqR'@s}&Uտ +G^:"΅nK\锔6c,JWW)ΎOF>2 Hn>t> )_[b9M`=Ew bJ)MRGK_WSq }-[rˀ>nԢa!FFZ橴D4l{,1ch tq(K4bPa͟T͙5GSdx("I$]ǥ)UBcܗFQ"n}H[ \Ghhscͮ,hqLTE Eހ8_fϪ+ҕD.- aQ%Ԛ`rZuy+ZߍNJS)Jܞ*aia| |Գ(rRsg \XAef2V\$XE])VKlJ"bWQeV}o)Qy J{{hAGdz>^*}:5ETWiϫr \1:jg3I w:%+o :WJQ)_v WOث填uЖ}o-1ӓnk|YXs-*Jd2Ej){GI,O~ܘ&4_O)&^W{hQȅZ@/-0FycD)=CE-tꪨYF|٥Pr@C\V#rZO4ƱŘ}ꘗ,ݶsAO]-Y]SMUs/ZF膆|l&DjOe"3Ps&pOlvYE}[YWtco٥RW M) Gr!vQ=mQPj4kxuӴvt5fkYe)tT \{TGIBeas6geB5l̅aO`s`SE@4Lh%kv>BpG+k/H@`"fϲb7-ka4*YӮsM_c~AMH+!zө8uspyT!&u\}Eҍ É\v [:o~lVV:j57A5p(j휦햾"EOv`%. ۸ӑ˗Kŝnz]TNYM::X=|-9ZrtoUW,-ETtu0SSoyl);sfHK0EMb%nwwJWL," s+R91ukbU ||T)xRҬ.E3EDT˸8fQ>[$:J\Vjo^;Ed3E5FRH.b_7qfk–^,Rn٦)nh^WOPN\(j&~k/VTnhN/9Q&oLX4y86ʼnnvumux |0_&`<>x_ bp04VͣG-ny|b7k3mWq9%6jwyj"t3myݤC8R7u84_%JYXm\x&i C#% Bon;앋ߪmNM>-.tfYt_UA@xҋ ׺'N BqC,tσ*D"kkR+=pD(9'TAc[f3xFxlRFb\F^X^{s&D%iCsr*{=St)[<-YvAsՂE ƫmתC̣{by]X/z? z+?$7~orf3}l022ֳH&/:__PM,;R Q ʖ.>{]&W"..:}QD^Y^uQ.AM!/8T2~ZP?sy=>kky8歳9E6*׳³E>,^ bwO, n12h×}̷u-?V߳hV$i u~ &2 echo "$usage" exit 1 ;; esac done if test -n "${debug}"; then qt_debug_char='d'; fi if test -n "${use_builtin_complex}"; then builtin_complex_define="_USE_BUILTIN_COMPLEX" else builtin_complex_define="" fi if test -n "${no_spinlock}"; then spinlock_define="NO_SPINLOCK" else spinlock_define="_POSIX_C_SOURCE=200809L" fi if test -n "${no_mp_floats}"; then mp_floats_define="" else mp_floats_define="_ENABLE_MP_FLOATS" fi if test -n "${no_ldouble_floats}"; then ldouble_floats_define="" else ldouble_floats_define="_ENABLE_LDOUBLE_FLOATS" fi is_absolute=`echo "${prefix}" | grep '^/'` if test -z "${is_absolute}"; then system_pwd="`which pwd`" prefix="`\"${system_pwd}\"`/${prefix}" fi; echo "Prefix: '${prefix}'" if test -n "${debug}"; then echo "Debug: yes" else echo "Debug: no" fi if test -n "${use_builtin_complex}"; then echo "Standard C99 complex: no (builtin)" else echo "Standard C99 complex: yes" fi if test -n "${no_spinlock}"; then echo "Spin locks: no" else echo "Spin locks: yes" fi echo "Testing for qmake..." if qmake -v &>/dev/null; then qt_version=`qmake -query QT_VERSION` echo "Found qmake (Qt ${qt_version})" major=`echo $qt_version | sed -e "s/\([0-9][0-9]*\).*/\1/"` minor=`echo $qt_version | sed -e "s/[0-9][0-9]*\.\([0-9][0-9]*\).*/\1/"` if test ${major} -ne 5 -o ${minor} -lt 0; then echo "*** ERROR: ${gui_pretty_name} requires Qt 5.0 or greater." exit 1 fi; else echo "*** ERROR: qmake not found. Install qmake and make sure it is in your PATH." >&2 exit 1 fi; if test -n "${win32}"; then which_qmake=`which qmake 2>/dev/null` if test -n "${which_qmake}"; then qt_bin_dir=`dirname "${which_qmake}"` qtcore4=`ls "${qt_bin_dir}" | grep "QtCore${qt_debug_char}4\.dll"` if test -f "${qt_bin_dir}/${qtcore4}"; then qtcore4_dll="${qtcore4}" echo "Found '${qtcore4_dll}'." fi; qtgui4=`ls "${qt_bin_dir}" | grep "QtGui${qt_debug_char}4\.dll"` if test -f "${qt_bin_dir}/${qtgui4}"; then qtgui4_dll="${qtgui4}" echo "Found '${qtgui4_dll}'." fi; fi fi #Used for common part of Makefiles config="VERSION_NUMBER = ${version_number} DEBUG = ${debug} BUILTIN_COMPLEX_DEFINE = ${builtin_complex_define} SPINLOCK_DEFINE = ${spinlock_define} MP_FLOATS_DEFINE = ${mp_floats_define} LDOUBLE_FLOATS_DEFINE = ${ldouble_floats_define} quiet-command = "'$(if $(VERB),$1,$(if $(2),@echo $2 && $1, @$1)) ' #Generate lib Makefile echo "Generating library Makefile..." echo "${config} TARGET_NAME = ${lib_bin} "> "${lib_dir}/Makefile" cat "${lib_dir}/Makefile.configure" >> "${lib_dir}/Makefile" #Generate command-line Makefile echo "Generating command-line Makefile..." echo "${config} TARGET_NAME = ${command_line_name} FRACTAL2D_LIB = ${lib_name} " > "${command_line_dir}/Makefile" cat "${command_line_dir}/Makefile.configure" >> "${command_line_dir}/Makefile" #Generate gui qmake project file echo "Generating gui qmake project file..." echo "${config} TARGET_NAME = ${gui_name} FRACTAL2D_LIB = ${lib_name} " > "${gui_dir}/${gui_pro_file}" cat "${gui_dir}/${gui_pro_file}.configure" >> "${gui_dir}/${gui_pro_file}" #Run qmake echo "Running qmake..." qmake -makefile "${gui_dir}/${gui_pro_file}" -o "${gui_dir}/Makefile" 2>/dev/null if test $? -ne 0; then echo "*** ERROR: Running qmake failed." exit 1 fi; #Generate main Makefile echo "Generating main Makefile..." #Set variables for installing/uninstalling echo "${config} PROJECT_NAME = ${project_name} LIB_DIR = ${lib_dir} BIN_DIR = ${bin_dir} COMMAND_LINE_DIR = ${command_line_dir} COMMAND_LINE_NAME = ${command_line_name} COMMAND_LINE_BINARY = ${command_line_bin} GUI_DIR = ${gui_dir} GUI_NAME = ${gui_name} GUI_BINARY = ${gui_bin} GUI_ICONS_DIR = ${gui_icons_dir} GUI_PRO_FILE = ${gui_pro_file} DOC_DIR = ${doc_dir} EXAMPLES_DIR = ${examples_dir} GENERATE_SAMPLES_SCRIPT = ${generate_samples_script} PREFIX = ${prefix}" > Makefile #Set specific variable for installing Qt DLLs on WIndows if test -n "${win32}"; then echo " GNU_BIN_DIR = ${gnu_bin_dir} QT_BIN_DIR = ${qt_bin_dir} QTCORE4_DLL = ${qtcore4_dll} QTGUI4_DLL = ${qtgui4_dll}" >> Makefile fi #Define main commands to installing/uninstalling cat Makefile.configure >> Makefile if test -z "${win32}"; then echo 'install: all $(CHK_DIR_EXISTS) "${PREFIX}/bin" || $(MKDIR) "${PREFIX}/bin" $(INSTALL_PROGRAM) "${COMMAND_LINE_DIR}/${BIN_DIR}/${COMMAND_LINE_BINARY}" "${PREFIX}/bin/" $(INSTALL_PROGRAM) "${GUI_DIR}/${BIN_DIR}/${GUI_BINARY}" "${PREFIX}/bin/"' >> Makefile if test -z "${debug}"; then echo ' $(STRIP_BINARY) "${PREFIX}/bin/${COMMAND_LINE_BINARY}"' >> Makefile echo ' $(STRIP_BINARY) "${PREFIX}/bin/${GUI_BINARY}"' >> Makefile fi echo ' $(CHK_DIR_EXISTS) "${PREFIX}/share/doc/${PROJECT_NAME}" || $(MKDIR) "${PREFIX}/share/doc/${PROJECT_NAME}" $(INSTALL_DIR) "${DOC_DIR}/." "${PREFIX}/share/doc/${PROJECT_NAME}/" $(CHK_DIR_EXISTS) "${PREFIX}/share/${PROJECT_NAME}" || $(MKDIR) "${PREFIX}/share/${PROJECT_NAME}" cd "${PREFIX}/share/${PROJECT_NAME}" && $(SYMLINK) "../doc/${PROJECT_NAME}" "${DOC_DIR}" && (cd - >/dev/null) $(INSTALL_DIR) "${EXAMPLES_DIR}" "${PREFIX}/share/${PROJECT_NAME}/" $(CHK_DIR_EXISTS) "${PREFIX}/share/${PROJECT_NAME}/${BIN_DIR}" || $(MKDIR) "${PREFIX}/share/${PROJECT_NAME}/${BIN_DIR}" cd "${PREFIX}/share/${PROJECT_NAME}/${BIN_DIR}" && $(SYMLINK) "../../../bin/${COMMAND_LINE_BINARY}" && (cd - >/dev/null) cd "${PREFIX}/share/${PROJECT_NAME}/${BIN_DIR}" && $(SYMLINK) "../../../bin/${GUI_BINARY}" && (cd - >/dev/null) $(INSTALL_PROGRAM) "${GENERATE_SAMPLES_SCRIPT}" "${PREFIX}/share/${PROJECT_NAME}/" $(CHK_DIR_EXISTS) "${PREFIX}/share/icons/hicolor/16x16/apps" || $(MKDIR) "${PREFIX}/share/icons/hicolor/16x16/apps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon16x16.png" "${PREFIX}/share/icons/hicolor/16x16/apps/${GUI_NAME}.png" $(CHK_DIR_EXISTS) "${PREFIX}/share/icons/hicolor/22x22/apps" || $(MKDIR) "${PREFIX}/share/icons/hicolor/22x22/apps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon22x22.png" "${PREFIX}/share/icons/hicolor/22x22/apps/${GUI_NAME}.png" $(CHK_DIR_EXISTS) "${PREFIX}/share/icons/hicolor/24x24/apps" || $(MKDIR) "${PREFIX}/share/icons/hicolor/24x24/apps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon24x24.png" "${PREFIX}/share/icons/hicolor/24x24/apps/${GUI_NAME}.png" $(CHK_DIR_EXISTS) "${PREFIX}/share/icons/hicolor/32x32/apps" || $(MKDIR) "${PREFIX}/share/icons/hicolor/32x32/apps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon32x32.png" "${PREFIX}/share/icons/hicolor/32x32/apps/${GUI_NAME}.png" $(CHK_DIR_EXISTS) "${PREFIX}/share/icons/hicolor/36x36/apps" || $(MKDIR) "${PREFIX}/share/icons/hicolor/36x36/apps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon36x36.png" "${PREFIX}/share/icons/hicolor/36x36/apps/${GUI_NAME}.png" $(CHK_DIR_EXISTS) "${PREFIX}/share/icons/hicolor/48x48/apps" || $(MKDIR) "${PREFIX}/share/icons/hicolor/48x48/apps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon48x48.png" "${PREFIX}/share/icons/hicolor/48x48/apps/${GUI_NAME}.png" $(CHK_DIR_EXISTS) "${PREFIX}/share/icons/hicolor/64x64/apps" || $(MKDIR) "${PREFIX}/share/icons/hicolor/64x64/apps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon64x64.png" "${PREFIX}/share/icons/hicolor/64x64/apps/${GUI_NAME}.png" $(CHK_DIR_EXISTS) "${PREFIX}/share/icons/hicolor/72x72/apps" || $(MKDIR) "${PREFIX}/share/icons/hicolor/72x72/apps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon72x72.png" "${PREFIX}/share/icons/hicolor/72x72/apps/${GUI_NAME}.png" $(CHK_DIR_EXISTS) "${PREFIX}/share/icons/hicolor/96x96/apps" || $(MKDIR) "${PREFIX}/share/icons/hicolor/96x96/apps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon96x96.png" "${PREFIX}/share/icons/hicolor/96x96/apps/${GUI_NAME}.png" $(CHK_DIR_EXISTS) "${PREFIX}/share/icons/hicolor/128x128/apps" || $(MKDIR) "${PREFIX}/share/icons/hicolor/128x128/apps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon128x128.png" "${PREFIX}/share/icons/hicolor/128x128/apps/${GUI_NAME}.png" $(CHK_DIR_EXISTS) "${PREFIX}/share/icons/hicolor/192x192/apps" || $(MKDIR) "${PREFIX}/share/icons/hicolor/192x192/apps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon192x192.png" "${PREFIX}/share/icons/hicolor/192x192/apps/${GUI_NAME}.png" $(CHK_DIR_EXISTS) "${PREFIX}/share/icons/hicolor/256x256/apps" || $(MKDIR) "${PREFIX}/share/icons/hicolor/256x256/apps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon256x256.png" "${PREFIX}/share/icons/hicolor/256x256/apps/${GUI_NAME}.png" $(CHK_DIR_EXISTS) "${PREFIX}/share/pixmaps" || $(MKDIR) "${PREFIX}/share/pixmaps" $(INSTALL_FILE) "${GUI_ICONS_DIR}/icon.xpm" "${PREFIX}/share/pixmaps/${GUI_NAME}.xpm" cd "${PREFIX}/share/pixmaps" && $(SYMLINK) "../icons/hicolor/256x256/apps/${GUI_NAME}.png" && (cd - >/dev/null) $(CHK_DIR_EXISTS) "${PREFIX}/share/applications" || $(MKDIR) "${PREFIX}/share/applications" $(INSTALL_FILE) "${GUI_DIR}/${GUI_NAME}.desktop" "${PREFIX}/share/applications/" uninstall: $(DEL_FILE) "${PREFIX}/bin/${COMMAND_LINE_BINARY}" $(DEL_FILE) "${PREFIX}/bin/${GUI_BINARY}" $(DEL_EMPTY_DIR) "${PREFIX}/bin" $(DEL_DIR) "${PREFIX}/share/doc/${PROJECT_NAME}" $(DEL_EMPTY_DIR) "${PREFIX}/share/doc" $(DEL_FILE) "${PREFIX}/share/${PROJECT_NAME}/${DOC_DIR}" $(DEL_DIR) "${PREFIX}/share/${PROJECT_NAME}/${EXAMPLES_DIR}" $(DEL_FILE) "${PREFIX}/share/${PROJECT_NAME}/${BIN_DIR}/${COMMAND_LINE_BINARY}" $(DEL_FILE) "${PREFIX}/share/${PROJECT_NAME}/${BIN_DIR}/${GUI_BINARY}" $(DEL_EMPTY_DIR) "${PREFIX}/share/${PROJECT_NAME}/${BIN_DIR}" $(DEL_FILE) "${PREFIX}/share/${PROJECT_NAME}/${GENERATE_SAMPLES_SCRIPT}" $(DEL_EMPTY_DIR) "${PREFIX}/share/${PROJECT_NAME}" $(DEL_FILE) "${PREFIX}/share/icons/hicolor/16x16/apps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/icons/hicolor/16x16/apps" $(DEL_FILE) "${PREFIX}/share/icons/hicolor/22x22/apps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/icons/hicolor/22x22/apps" $(DEL_FILE) "${PREFIX}/share/icons/hicolor/24x24/apps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/icons/hicolor/24x24/apps" $(DEL_FILE) "${PREFIX}/share/icons/hicolor/32x32/apps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/icons/hicolor/32x32/apps" $(DEL_FILE) "${PREFIX}/share/icons/hicolor/36x36/apps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/icons/hicolor/36x36/apps" $(DEL_FILE) "${PREFIX}/share/icons/hicolor/48x48/apps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/icons/hicolor/48x48/apps" $(DEL_FILE) "${PREFIX}/share/icons/hicolor/64x64/apps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/icons/hicolor/64x64/apps" $(DEL_FILE) "${PREFIX}/share/icons/hicolor/72x72/apps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/icons/hicolor/72x72/apps" $(DEL_FILE) "${PREFIX}/share/icons/hicolor/96x96/apps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/icons/hicolor/96x96/apps" $(DEL_FILE) "${PREFIX}/share/icons/hicolor/128x128/apps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/icons/hicolor/128x128/apps" $(DEL_FILE) "${PREFIX}/share/icons/hicolor/192x192/apps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/icons/hicolor/192x192/apps" $(DEL_FILE) "${PREFIX}/share/icons/hicolor/256x256/apps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/icons/hicolor/256x256/apps" $(DEL_FILE) "${PREFIX}/share/applications/${GUI_NAME}.desktop" $(DEL_EMPTY_DIR) "${PREFIX}/share/applications" $(DEL_FILE) "${PREFIX}/share/pixmaps/${GUI_NAME}.xpm" $(DEL_FILE) "${PREFIX}/share/pixmaps/${GUI_NAME}.png" $(DEL_EMPTY_DIR) -p "${PREFIX}/share/pixmaps" ' >> Makefile else echo 'install: all $(CHK_DIR_EXISTS) "${PREFIX}/${PROJECT_NAME}" || $(MKDIR) "${PREFIX}/${PROJECT_NAME}" $(INSTALL_PROGRAM) "${COMMAND_LINE_DIR}/${BIN_DIR}/${COMMAND_LINE_BINARY}" "${PREFIX}/${PROJECT_NAME}/" $(INSTALL_PROGRAM) "${GUI_DIR}/${BIN_DIR}/${GUI_BINARY}" "${PREFIX}/${PROJECT_NAME}/"' >> Makefile if test -z "${debug}"; then echo ' $(STRIP_BINARY) "${PREFIX}/${PROJECT_NAME}/${COMMAND_LINE_BINARY}"' >> Makefile echo ' $(STRIP_BINARY) "${PREFIX}/${PROJECT_NAME}/${GUI_BINARY}"' >> Makefile fi echo ' $(INSTALL_PROGRAM) "${GENERATE_SAMPLES_SCRIPT}" "${PREFIX}/${PROJECT_NAME}/" $(INSTALL_DIR) "${DOC_DIR}" "${PREFIX}/${PROJECT_NAME}/" $(INSTALL_DIR) "${EXAMPLES_DIR}" "${PREFIX}/${PROJECT_NAME}/"' >> Makefile if test -n "${qtcore4_dll}"; then echo ' $(INSTALL_FILE) "${QT_BIN_DIR}/${QTCORE4_DLL}" "${PREFIX}/${PROJECT_NAME}/"' >> Makefile fi if test -n "${qtgui4_dll}"; then echo ' $(INSTALL_FILE) "${QT_BIN_DIR}/${QTGUI4_DLL}" "${PREFIX}/${PROJECT_NAME}/"' >> Makefile fi echo ' $(INSTALL_FILE) "ChangeLog" "${PREFIX}/${PROJECT_NAME}/"' >> Makefile echo ' $(INSTALL_FILE) "README" "${PREFIX}/${PROJECT_NAME}/"' >> Makefile echo ' uninstall: $(DEL_FILE) "${PREFIX}/${PROJECT_NAME}/${COMMAND_LINE_BINARY}" $(DEL_FILE) "${PREFIX}/${PROJECT_NAME}/${GUI_BINARY}" $(DEL_FILE) "${PREFIX}/${PROJECT_NAME}/${GENERATE_SAMPLES_SCRIPT}" $(DEL_DIR) "${PREFIX}/${PROJECT_NAME}/${DOC_DIR}" $(DEL_DIR) "${PREFIX}/${PROJECT_NAME}/${EXAMPLES_DIR}"' >> Makefile if test -n "${qtcore4_dll}"; then echo ' $(DEL_FILE) "${PREFIX}/${PROJECT_NAME}/${QTCORE4_DLL}"' >> Makefile fi if test -n "${qtgui4_dll}"; then echo ' $(DEL_FILE) "${PREFIX}/${PROJECT_NAME}/${QTGUI4_DLL}"' >> Makefile fi echo ' $(DEL_FILE) "${PREFIX}/${PROJECT_NAME}/ChangeLog"' >> Makefile echo ' $(DEL_FILE) "${PREFIX}/${PROJECT_NAME}/README"' >> Makefile echo ' $(DEL_EMPTY_DIR) "${PREFIX}/${PROJECT_NAME}"' >> Makefile echo ' $(DEL_EMPTY_DIR) "${PREFIX}"' >> Makefile fi echo "#!/bin/bash ./configure -prefix \"${prefix}\" "${debug}" "${no_spinlock}" "${use_builtin_complex}" " > config.status chmod +x config.status >/dev/null echo "Configure finished. Run 'make' to build ${project_pretty_name} and 'make install' to install it." if test -n "${win32}"; then echo "You might need to add some DLLs manually to complete install." fi; fractalnow-0.8.2/gui/include/color_button.h000664 001750 001750 00000002644 13175112471 020706 0ustar00mpegmpeg000000 000000 /* * color_button.h -- part of FractalNow * * Copyright (c) 2012 Marc Pegon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file color_button.h * \brief Header file introducing ColorButton class. * * \author Marc Pegon */ #ifndef _COLOR_BUTTON__H__ #define _COLOR_BUTTON__H__ #include #include class ColorButton : public QPushButton { Q_OBJECT public: ColorButton(QWidget *parent = 0); const QColor ¤tColor() const; private: QColor color; QColorDialog *colorDialog; void updateIcon(); public slots: void setCurrentColor(const QColor &color); private slots: void openColorDialog(); signals: void currentColorChanged(const QColor &color); }; #endif fractalnow-0.8.2/gui/include/000775 001750 001750 00000000000 13175136654 016027 5ustar00mpegmpeg000000 000000 fractalnow-0.8.2/gui/src/hoverpoints.cpp000664 001750 001750 00000021721 13175125335 020254 0ustar00mpegmpeg000000 000000 /**************************************************************************** ** ** This file is based on some files of the demonstration applications of the ** Qt Toolkit. ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Modified to be used as a part of FractalNow: ** Copyright (c) 2012 Marc Pegon ** ** This file can be distributed and/or modified under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation. ** You should have received a copy of the GNU General Public License ** along with this file; if not, write to the Free Software Foundation, Inc., ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ** ****************************************************************************/ #include "hoverpoints.h" HoverPoints::HoverPoints(QWidget *widget, PointShape shape) : QObject(widget) { m_widget = widget; widget->installEventFilter(this); widget->setAttribute(Qt::WA_AcceptTouchEvents); m_connectionType = CurveConnection; m_sortType = NoSort; m_shape = shape; m_pointPen = QPen(QColor(255, 255, 255, 191), 1); m_connectionPen = QPen(QColor(255, 255, 255, 127), 2); m_pointBrush = QBrush(QColor(191, 191, 191, 127)); m_pointSize = QSize(11, 11); m_currentIndex = -1; m_editable = true; m_enabled = true; connect(this, SIGNAL(pointsChanged(QPolygonF)), m_widget, SLOT(update())); } void HoverPoints::setEnabled(bool enabled) { if (m_enabled != enabled) { m_enabled = enabled; m_widget->update(); } } bool HoverPoints::eventFilter(QObject *object, QEvent *event) { if (object == m_widget && m_enabled) { switch (event->type()) { case QEvent::MouseButtonPress: { if (!m_fingerPointMapping.isEmpty()) { return true; } QMouseEvent *me = (QMouseEvent *) event; QPointF clickPos = me->pos(); int index = -1; for (int i=0; ibutton() == Qt::LeftButton) { if (index == -1) { if (!m_editable) return false; int pos = 0; // Insert sort for x or y if (m_sortType == XSort) { for (int i=0; i clickPos.x()) { pos = i; break; } } } else if (m_sortType == YSort) { for (int i=0; i clickPos.y()) { pos = i; break; } } } m_points.insert(pos, clickPos); m_locks.insert(pos, 0); m_currentIndex = pos; firePointChange(); } else { m_currentIndex = index; } return true; } else if (me->button() == Qt::RightButton) { if (index >= 0 && m_editable) { if (m_locks[index] == 0) { m_locks.remove(index); m_points.remove(index); } firePointChange(); return true; } } } break; case QEvent::MouseButtonRelease: if (!m_fingerPointMapping.isEmpty()) { return true; } m_currentIndex = -1; break; case QEvent::MouseMove: if (!m_fingerPointMapping.isEmpty()) { return true; } if (m_currentIndex >= 0) { movePoint(m_currentIndex, ((QMouseEvent *)event)->pos()); } break; case QEvent::TouchBegin: case QEvent::TouchUpdate: { const QTouchEvent *const touchEvent = static_cast(event); const QList points = touchEvent->touchPoints(); const qreal pointSize = qMax(m_pointSize.width(), m_pointSize.height()); foreach (const QTouchEvent::TouchPoint &touchPoint, points) { const int id = touchPoint.id(); switch (touchPoint.state()) { case Qt::TouchPointPressed: { // find the point, move it QSet activePoints = QSet::fromList(m_fingerPointMapping.values()); int activePoint = -1; qreal distance = -1; const int pointsCount = m_points.size(); const int activePointCount = activePoints.size(); if (pointsCount == 2 && activePointCount == 1) { // only two points activePoint = activePoints.contains(0) ? 1 : 0; } else { for (int i=0; i::iterator it = m_fingerPointMapping.find(id); movePoint(it.value(), touchPoint.pos()); m_fingerPointMapping.erase(it); } break; case Qt::TouchPointMoved: { // move the point const int pointIdx = m_fingerPointMapping.value(id, -1); if (pointIdx >= 0) { // do we track this point? movePoint(pointIdx, touchPoint.pos()); } } break; default: break; } } if (m_fingerPointMapping.isEmpty()) { event->ignore(); return false; } else { return true; } } break; case QEvent::TouchEnd: if (m_fingerPointMapping.isEmpty()) { event->ignore(); return false; } return true; break; case QEvent::Resize: { QResizeEvent *e = (QResizeEvent *) event; if (e->oldSize().width() == 0 || e->oldSize().height() == 0) { break; } qreal stretch_x = e->size().width() / qreal(e->oldSize().width()); qreal stretch_y = e->size().height() / qreal(e->oldSize().height()); for (int i=0; i right || (lock & HoverPoints::LockToRight)) p.setX(right); if (p.y() < top || (lock & HoverPoints::LockToTop)) p.setY(top); else if (p.y() > bottom || (lock & HoverPoints::LockToBottom)) p.setY(bottom); return p; } void HoverPoints::setPoints(const QPolygonF &points) { if (points.size() != m_points.size()) { m_fingerPointMapping.clear(); } m_points.clear(); for (int i=0; i 0) { m_locks.resize(m_points.size()); m_locks.fill(0); } } void HoverPoints::movePoint(int index, const QPointF &point, bool emitUpdate) { m_points[index] = bound_point(point, boundingRect(), m_locks.at(index)); if (emitUpdate) { firePointChange(); } } inline static bool x_less_than(const QPointF &p1, const QPointF &p2) { return p1.x() < p2.x(); } inline static bool y_less_than(const QPointF &p1, const QPointF &p2) { return p1.y() < p2.y(); } void HoverPoints::firePointChange() { if (m_sortType != NoSort) { QPointF oldCurrent; if (m_currentIndex != -1) { oldCurrent = m_points[m_currentIndex]; } if (m_sortType == XSort) { qSort(m_points.begin(), m_points.end(), x_less_than); } else if (m_sortType == YSort) { qSort(m_points.begin(), m_points.end(), y_less_than); } // Compensate for changed order... if (m_currentIndex != -1) { for (int i=0; i * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 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. */ /** * \file main_window.h * \brief Header file introducing MainWindow class. * * \author Marc Pegon */ #ifndef __MAIN_WINDOW_H__ #define __MAIN_WINDOW_H__ #include "command_line.h" #include "export_fractal_image_dialog.h" #include "fractal_config_widget.h" #include "fractal_explorer.h" #include "fractal_rendering_widget.h" #include "fractalnow.h" #include #include #include #include #include #include #include #define DEFAULT_EXPLORER_WIDTH (uint)(640) #define DEFAULT_EXPLORER_HEIGHT (uint)(512) class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(int argc, char *argv[]); ~MainWindow(); private: enum FileType { UNKNOWN_FILE=0, CONFIG_FILE, FRACTAL_FILE, RENDER_FILE, GRADIENT_FILE }; ExportFractalImageDialog *exportFractalImageDialog; QDockWidget *fractalDock, *renderDock, *otherDock; QToolBar *toolBar; FractalExplorer *fractalExplorer; FractalConfigWidget *fractalConfigWidget; FractalRenderingWidget *fractalRenderingWidget; QSpinBox *preferredImageWidthSpinBox; QSpinBox *preferredImageHeightSpinBox; QCheckBox *solidGuessingCheckBox; QCheckBox *useCacheCheckBox; QSpinBox *cacheSizeSpinBox; QComboBox *floatTypeComboBox; QSpinBox *MPFloatPrecisionSpinBox; QWidget *editMPFloatPrecisionWidget; QAction *adaptExplorerToWindowAction; uint_fast32_t fractalExplorerNbThreads; uint_fast32_t exportImageNbThreads; bool adaptExplorerSize; uint lastPreferredExplorerWidth, lastPreferredExplorerHeight; uint lastWindowWidth, lastWindowHeight; QString imageDir; QString configDir; QString gradientDir; bool useCache; int cacheSize; bool solidGuessing; QAction *switchFullScreenAction; enum FileType getFileType(QString fileName); void saveSettings(); void loadSettings(); void loadFile(QString fileName); void loadConfigFile(QString fileName); void loadFractalFile(QString fileName); void loadRenderingFile(QString fileName); void loadGradientFile(QString fileName); void openFile(QString fileName); void dragEnterEvent(QDragEnterEvent *event); void dropEvent(QDropEvent *event); private slots: void delayedInit(); void aboutQt(); void aboutQFractalNow(); void adaptExplorerToWindow(bool checked); void exportImage(); void openConfigFile(); void saveConfigFile(); void openGradientFile(); void saveGradientFile(); void onPreferredImageWidthChanged(); void onPreferredImageHeightChanged(); void onCacheSizeChanged(); void onFloatTypeChanged(int index); void editMPFloatPrecision(); void switchFullScreenMode(bool checked); void escapeFullScreen(); }; #endif