-add_subdirectory(mandelbrot)
add_subdirectory(potd)
add_subdirectory(virus)
add_subdirectory(weather)
+++ /dev/null
-find_package(Eigen2 2.0.3)
-macro_log_feature(EIGEN2_FOUND "Eigen2" "Eigen2 enables the Mandelbrot wallpaper plugin." "http://eigen.tuxfamily.org" FALSE "2.0.3")
-
-if(EIGEN2_FOUND)
-
-
-project(plasma-wallpaper-mandelbrot)
-
-include_directories(${EIGEN2_INCLUDE_DIR})
-
-set(mandelbrot_SRCS
- mandelbrot.cpp
- tile.cpp
- renderthread.cpp
- render_with_arch_defaults.cpp
- detectSSE2.cpp
- mix.cpp
-)
-
-# The x86-specific stuff below does not mean that this code is non-portable!
-# The idea is that x86 (32bit) is the ONLY major architecture on which vectorization (SSE2) may or may not be available.
-# Other platforms have either ALWAYS vectorization (x86-64, PPC...) or NEVER in which case Eigen takes care of the details.
-# Only on x86 do we have to take special care to compile 2 paths, one with SSE and one without, and choose the right one
-# at runtime.
-
-# MANDELBROT_ON_X86 will be non-empty if the CPU name contains "86" which we only use to make sure we may ask the
-# compiler to enable SSE. At this stage we don't tell the difference between x86 and X86-64, and for 64bit CPUs,
-# we don't know if we're in 32bit or 64bit mode. That will be done in the source code using preprocessor symbols.
-string(REGEX MATCH "86" MANDELBROT_ON_X86 "${CMAKE_SYSTEM_PROCESSOR}")
-if(MANDELBROT_ON_X86)
- set(mandelbrot_SRCS
- ${mandelbrot_SRCS}
- render_with_SSE2_explicitly_enabled.cpp
- )
- if(CMAKE_COMPILER_IS_GNUCXX)
- set(SSE2_CXX_FLAG "-msse2")
- elseif(MSVC)
- set(SSE2_CXX_FLAG "/arch:SSE2")
- else(CMAKE_COMPILER_IS_GNUCXX)
- set(SSE2_CXX_FLAG "")
- endif(CMAKE_COMPILER_IS_GNUCXX)
-endif(MANDELBROT_ON_X86)
-
-if(CMAKE_COMPILER_IS_GNUCXX)
- set(NODEBUGINFO_CXX_FLAG "-g0")
-else(CMAKE_COMPILER_IS_GNUCXX)
- set(NODEBUGINFO_CXX_FLAG "")
-endif(CMAKE_COMPILER_IS_GNUCXX)
-
-# for code using Eigen, function inlining is important. Normally one doesn't need to pass -finline explicitly
-# as -O2 is enough, but here there may already be a -fno-inline option passed beforehand, so we use -finline
-# to cancel it. Another, separate issue, is that -fno-inline seems breaks the rendering, giving a blank result.
-# I'm not sure why, my best guess is an incompatibility between -fno-inline and SSE intrinsics.
-
-if(CMAKE_COMPILER_IS_GNUCXX)
- set(INLINING_CXX_FLAG "-finline")
-else(CMAKE_COMPILER_IS_GNUCXX)
- set(INLINING_CXX_FLAG "")
-endif(CMAKE_COMPILER_IS_GNUCXX)
-
-if(MANDELBROT_ON_X86)
- set_source_files_properties(
- render_with_SSE2_explicitly_enabled.cpp
- PROPERTIES COMPILE_FLAGS "-O2 -DEIGEN_NO_DEBUG ${INLINING_CXX_FLAG} ${NODEBUGINFO_CXX_FLAG} ${SSE2_CXX_FLAG}"
- )
-endif(MANDELBROT_ON_X86)
-
-set_source_files_properties(
- render_with_arch_defaults.cpp
- PROPERTIES COMPILE_FLAGS "-O2 -DEIGEN_NO_DEBUG ${INLINING_CXX_FLAG} ${NODEBUGINFO_CXX_FLAG}"
-)
-
-set_source_files_properties(
- mix.cpp
- PROPERTIES COMPILE_FLAGS "-O2 -DEIGEN_NO_DEBUG ${INLINING_CXX_FLAG} ${NODEBUGINFO_CXX_FLAG}"
-)
-
-set_source_files_properties(
- renderthread.cpp
- PROPERTIES COMPILE_FLAGS "-O2 -DEIGEN_NO_DEBUG ${INLINING_CXX_FLAG} "
-)
-
-kde4_add_plugin(plasma_wallpaper_mandelbrot ${mandelbrot_SRCS})
-target_link_libraries(plasma_wallpaper_mandelbrot ${KDE4_PLASMA_LIBS} ${KDE4_KIO_LIBS} ${KDE4_SOLID_LIBS})
-
-install(TARGETS plasma_wallpaper_mandelbrot DESTINATION ${KDE4_PLUGIN_INSTALL_DIR})
-install(FILES plasma-wallpaper-mandelbrot.desktop DESTINATION ${KDE4_SERVICES_INSTALL_DIR})
-
-endif(EIGEN2_FOUND)
+++ /dev/null
-#! /usr/bin/env bash
-$EXTRACTRC *.ui >> rc.cpp
-$XGETTEXT *.cpp -o $podir/plasma_wallpaper_mandelbrot.pot
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>Config</class>
- <widget class="QWidget" name="Config">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>465</width>
- <height>257</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Color</string>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>&Inside color:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="buddy">
- <cstring>m_color1</cstring>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="KColorButton" name="m_color1">
- <property name="color">
- <color>
- <red>70</red>
- <green>90</green>
- <blue>130</blue>
- </color>
- </property>
- <property name="defaultColor">
- <color>
- <red>70</red>
- <green>90</green>
- <blue>130</blue>
- </color>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>68</width>
- <height>18</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_6">
- <property name="text">
- <string>&Frontier color:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="buddy">
- <cstring>m_color2</cstring>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <widget class="KColorButton" name="m_color2">
- <property name="color">
- <color>
- <red>70</red>
- <green>90</green>
- <blue>130</blue>
- </color>
- </property>
- <property name="defaultColor">
- <color>
- <red>70</red>
- <green>90</green>
- <blue>130</blue>
- </color>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>93</width>
- <height>18</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_7">
- <property name="text">
- <string>&Outside color:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="buddy">
- <cstring>m_color3</cstring>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_4">
- <item>
- <widget class="KColorButton" name="m_color3">
- <property name="color">
- <color>
- <red>70</red>
- <green>90</green>
- <blue>130</blue>
- </color>
- </property>
- <property name="defaultColor">
- <color>
- <red>70</red>
- <green>90</green>
- <blue>130</blue>
- </color>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_4">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>93</width>
- <height>13</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_8">
- <property name="text">
- <string>&Quality:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="buddy">
- <cstring>m_quality</cstring>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="KComboBox" name="m_quality">
- <item>
- <property name="text">
- <string>Low</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Medium</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>High</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Very high (4x sampling)</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Highest (16x sampling)</string>
- </property>
- </item>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>92</width>
- <height>23</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>&Lock view:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="buddy">
- <cstring>m_lock</cstring>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QCheckBox" name="m_lock">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="6" column="1">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>24</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="5" column="1">
- <widget class="QLabel" name="label_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="text">
- <string>Use the mouse to navigate through the Mandelbrot set. Note: certain activities, such as Folder View, do not allow that.</string>
- </property>
- <property name="scaledContents">
- <bool>false</bool>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <customwidgets>
- <customwidget>
- <class>KComboBox</class>
- <extends>QComboBox</extends>
- <header>kcombobox.h</header>
- </customwidget>
- <customwidget>
- <class>KColorButton</class>
- <extends>QPushButton</extends>
- <header>kcolorbutton.h</header>
- </customwidget>
- </customwidgets>
- <resources/>
- <connections/>
- <designerdata>
- <property name="gridDeltaX">
- <number>10</number>
- </property>
- <property name="gridDeltaY">
- <number>10</number>
- </property>
- <property name="gridSnapX">
- <bool>true</bool>
- </property>
- <property name="gridSnapY">
- <bool>true</bool>
- </property>
- <property name="gridVisible">
- <bool>true</bool>
- </property>
- </designerdata>
-</ui>
+++ /dev/null
-// Copyright 2007 Christopher Blauvelt <cblauvelt@gmail.com>
-// Copyright 2009 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-//QT specific includes
-#include <QList>
-#include <QString>
-
-//solid specific includes
-#include <solid/device.h>
-#include <solid/deviceinterface.h>
-#include <solid/processor.h>
-
-bool system_has_SSE2()
-{
- QList<Solid::Device> list = Solid::Device::listFromType(Solid::DeviceInterface::Processor, QString());
-
- if (list.isEmpty()) {
- // because in the magical world of Solid, we can have no CPUs in our computer
- return false;
- }
-
- Solid::Processor::InstructionSets extensions = list[0].as<Solid::Processor>()->instructionSets();
- return (bool)(extensions & Solid::Processor::IntelSse2);
-}
+++ /dev/null
-// Copyright 2008-2009 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef GLOBAL_HEADER
-#define GLOBAL_HEADER
-
-#define TILING_SIZE 20
-
-#define MAX_PACKET_SIZE 4
-#define MAX_SUPERSAMPLING 4
-
-
-#if (defined(__i386__) || defined(_M_IX86)) && !(defined(__x86_64__) || defined(_M_X64))
-#define HAVE_PATH_WITH_SSE2_EXPLICTLY_ENABLED
-#endif
-
-#define CLAMP(val, min, max) qMin(qMax(val, min), max)
-
-#define MANDELBROT_CENTER_KEY "mandelbrotcenter"
-#define MANDELBROT_ZOOM_KEY "mandelbrotzoom"
-#define MANDELBROT_COLOR1_KEY "mandelbrotcolor1"
-#define MANDELBROT_COLOR2_KEY "mandelbrotcolor2"
-#define MANDELBROT_COLOR3_KEY "mandelbrotcolor3"
-#define MANDELBROT_QUALITY_KEY "mandelbrotquality"
-#define MANDELBROT_LOCK_KEY "mandelbrotlock"
-
-#define MANDELBROT_QIMAGE_FORMAT QImage::Format_RGB32
-
-class MandelbrotTile;
-class Mandelbrot;
-bool system_has_SSE2();
-
-#endif
+++ /dev/null
-// Copyright 2008-2010 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#include "mandelbrot.h"
-#include <iostream>
-
-#include <cmath>
-#include <QtGui/qgraphicssceneevent.h>
-#include <kfiledialog.h>
-#include <QByteArray>
-#include <QBuffer>
-#include <kio/job.h>
-//#include <KDebug>
-
-const qreal MOUSE_MMB_SPEED = (qreal)10.;
-const qreal MOUSE_WHEEL_SPEED = (qreal)0.002;
-
-K_EXPORT_PLASMA_WALLPAPER(mandelbrot, Mandelbrot)
-
-Mandelbrot::Mandelbrot(QObject *parent, const QVariantList &args)
- : Plasma::Wallpaper(parent, args), m_image(0), m_tiling(this),
- m_exportImageAction(i18n("Export Mandelbrot image..."), this),
- m_exportConfigAction(i18n("Export Mandelbrot parameters..."), this),
- m_importConfigAction(i18n("Import Mandelbrot parameters..."), this),
- m_abortRenderingAsSoonAsPossible(false),
- m_imageIsReady(false),
- m_firstInit(true)
-{
- setPreviewDuringConfiguration(true);
- qRegisterMetaType<MandelbrotTile>();
- m_hasSSE2 = system_has_SSE2();
- m_renderThreadCount = QThread::idealThreadCount();
- m_renderThreads = new MandelbrotRenderThread*[m_renderThreadCount];
- for(int th = 0; th < m_renderThreadCount; th++) m_renderThreads[th] = new MandelbrotRenderThread(this);
- setUsingRenderingCache(true);
-
- QList<QAction*> actionsList;
- actionsList.append(&m_exportImageAction);
- actionsList.append(&m_exportConfigAction);
- actionsList.append(&m_importConfigAction);
- setContextualActions(actionsList);
-
- connect(this, SIGNAL(renderHintsChanged()), this, SLOT(checkRenderHints()));
- connect(&m_exportImageAction, SIGNAL(triggered()), this, SLOT(exportImage()));
- connect(&m_exportConfigAction, SIGNAL(triggered()), this, SLOT(exportConfig()));
- connect(&m_importConfigAction, SIGNAL(triggered()), this, SLOT(importConfig()));
-}
-
-Mandelbrot::~Mandelbrot()
-{
- abortRendering();
- // the user may have moved the viewpoint, so we must save the config on exit (and that takes care of the cache, too)
- emit(configNeedsSaving());
- for(int th = 0; th < m_renderThreadCount; th++) delete m_renderThreads[th];
- delete[] m_renderThreads;
- delete m_image;
-}
-
-void Mandelbrot::updateCache()
-{
- // Don't let the mini-previewer in Desktop Settings affect the cache.
- if(isPreviewing()) return;
-
- QString k = key();
-
- // if the view parameters changed since we loaded from cache, or if we couldn't load from cache
- if(k != m_cacheKey)
- {
- // remove old image from cache
- //kDebug() << "remove " << m_cacheKey;
- insertIntoCache(m_cacheKey, QImage());
-
- // if the image is ready to be cached, cache it
- if(m_imageIsReady) {
- //kDebug() << "caching " << k << " replacing " << m_cacheKey;
- insertIntoCache(k, *m_image);
- m_cacheKey = k;
- }
- }
- //else kDebug() << k << " is already cached";
-}
-
-void Mandelbrot::paint(QPainter *painter, const QRectF& exposedRect)
-{
- painter->drawImage(exposedRect, *m_image, exposedRect.translated(-boundingRect().topLeft()));
-}
-
-void Mandelbrot::save(KConfigGroup &config)
-{
- if (!isPreviewing())
- {
- config.writeEntry(MANDELBROT_CENTER_KEY, m_center);
- config.writeEntry(MANDELBROT_ZOOM_KEY, m_zoom);
- }
-
- config.writeEntry(MANDELBROT_COLOR1_KEY, m_color1);
- config.writeEntry(MANDELBROT_COLOR2_KEY, m_color2);
- config.writeEntry(MANDELBROT_COLOR3_KEY, m_color3);
- config.writeEntry(MANDELBROT_QUALITY_KEY, m_quality);
- config.writeEntry(MANDELBROT_LOCK_KEY, int(m_lock));
- // and this is where we update the cache. It's important to update the cache at the same time we save the config.
- // Otherwise we could easily have stale cached images, or missing ones, for example in case of a crash.
- updateCache();
-}
-
-void Mandelbrot::readConfig(const KConfigGroup &config, int options)
-{
- QString old_key = key();
-
- if(options & ReadViewpoint)
- {
- m_center = config.readEntry(MANDELBROT_CENTER_KEY, QPointF(qreal(-0.25),qreal(0)));
- m_zoom = config.readEntry(MANDELBROT_ZOOM_KEY, qreal(4));
- }
-
- m_color1 = config.readEntry(MANDELBROT_COLOR1_KEY, QColor(0,0,0));
- m_color2 = config.readEntry(MANDELBROT_COLOR2_KEY, QColor(255,255,255));
- m_color3 = config.readEntry(MANDELBROT_COLOR3_KEY, QColor(0,0,255));
- m_quality = qBound(0, config.readEntry(MANDELBROT_QUALITY_KEY, 1), 4);
-
- if(options & ReadLockStatus)
- {
- m_lock = Qt::CheckState(config.readEntry(MANDELBROT_LOCK_KEY, int(Qt::Unchecked)));
- }
-
- if(key() != old_key)
- {
- abortRendering();
-
- if(!m_image || m_image->size() != boundingRect().size())
- {
- delete m_image;
- m_image = new QImage(width(), height(), MANDELBROT_QIMAGE_FORMAT);
- QPainter(m_image).fillRect(m_image->rect(), Qt::black);
- }
-
- loadFromCacheOrStartRendering();
- }
-}
-
-void Mandelbrot::init(const KConfigGroup &config)
-{
- readConfig(config, (m_firstInit?ReadViewpoint:0) | ReadLockStatus);
- m_firstInit = false;
-}
-
-QWidget* Mandelbrot::createConfigurationInterface(QWidget* parent)
-{
- QWidget *widget = new QWidget(parent);
- m_ui.setupUi(widget);
-
- m_ui.m_color1->setColor(m_color1);
- m_ui.m_color2->setColor(m_color2);
- m_ui.m_color3->setColor(m_color3);
- m_ui.m_quality->setCurrentIndex(m_quality);
- m_ui.m_lock->setCheckState(m_lock);
- connect(m_ui.m_color1, SIGNAL(changed(QColor)), this, SLOT(setColor1(QColor)));
- connect(m_ui.m_color2, SIGNAL(changed(QColor)), this, SLOT(setColor2(QColor)));
- connect(m_ui.m_color3, SIGNAL(changed(QColor)), this, SLOT(setColor3(QColor)));
- connect(m_ui.m_quality, SIGNAL(activated(int)), this, SLOT(setQuality(int)));
- connect(m_ui.m_lock, SIGNAL(stateChanged(int)), this, SLOT(setLock(int)));
-
- connect(this, SIGNAL(settingsChanged(bool)), parent, SLOT(settingsChanged(bool)));
-
- return widget;
-}
-
-void Mandelbrot::setColor1(const QColor& color1)
-{
- abortRendering();
- m_color1 = color1;
- startRendering();
- emit settingsChanged(true);
-}
-
-void Mandelbrot::setColor2(const QColor& color2)
-{
- abortRendering();
- m_color2 = color2;
- startRendering();
- emit settingsChanged(true);
-}
-
-void Mandelbrot::setColor3(const QColor& color3)
-{
- abortRendering();
- m_color3 = color3;
- startRendering();
- emit settingsChanged(true);
-}
-
-void Mandelbrot::setQuality(int quality)
-{
- abortRendering();
- m_quality = quality;
- startRendering();
- emit settingsChanged(true);
-}
-
-void Mandelbrot::setLock(int lock)
-{
- m_lock = Qt::CheckState(lock);
- emit settingsChanged(true);
-}
-
-void Mandelbrot::checkRenderHints()
-{
- if (m_image && m_image->size() != boundingRect().size()) {
- abortRendering();
- delete m_image;
- m_image = new QImage(width(), height(), MANDELBROT_QIMAGE_FORMAT);
- QPainter(m_image).fillRect(m_image->rect(), Qt::black);
- loadFromCacheOrStartRendering();
- }
-}
-
-void Mandelbrot::mousePressEvent(QGraphicsSceneMouseEvent *event)
-{
- event->ignore();
- if(m_lock) return;
- m_mousePressPos = m_mouseLastMovePos = event->pos();
- m_mousePressedButtons = event->buttons();
- if(event->buttons() & (Qt::LeftButton|Qt::MiddleButton)) event->accept();
-}
-
-void Mandelbrot::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
-{
- event->ignore();
- if(m_lock) return;
- if(m_mousePressedButtons & (Qt::LeftButton|Qt::MiddleButton)) event->accept();
-}
-
-void Mandelbrot::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
-{
- event->ignore();
- if(m_lock) return;
- if(event->buttons() & (Qt::LeftButton|Qt::MiddleButton)) event->accept();
-
- QPointF delta = event->pos() - m_mouseLastMovePos;
- m_mouseLastMovePos = event->pos();
-
- if(event->buttons() & Qt::MiddleButton)
- {
- zoomView(m_mousePressPos, std::exp(MOUSE_MMB_SPEED * qreal(delta.y()) / height()));
- }
-
- if(event->buttons() & Qt::LeftButton)
- {
- translateView(delta);
- }
-}
-
-void Mandelbrot::wheelEvent(QGraphicsSceneWheelEvent *event)
-{
- event->ignore();
- if(m_lock) return;
- event->accept();
- zoomView(event->pos(), std::exp(-MOUSE_WHEEL_SPEED * event->delta()));
-}
-
-void Mandelbrot::abortRendering()
-{
- m_abortRenderingAsSoonAsPossible = true;
- for(int i = 0; i < m_renderThreadCount; i++) m_renderThreads[i]->wait();
- m_abortRenderingAsSoonAsPossible = false;
-}
-
-void Mandelbrot::loadFromCacheOrStartRendering()
-{
- QString k = key();
- if(findInCache(k, *m_image))
- {
- if(m_image->size() == boundingRect().size()) {
- //kDebug() << "image " << k << " found in cache and has the wanted size";
- m_image->convertToFormat(MANDELBROT_QIMAGE_FORMAT);
- m_cacheKey = k;
- m_imageIsReady = true;
- update(m_image->rect());
- }
- else {
- //kDebug() << "image " << k << " found in cache but hasn't the wanted size. Removing it, and re-rendering.";
- insertIntoCache(k, QImage());
- startRendering();
- }
- }
- else
- {
- //kDebug() << "image " << k << " not found in cache";
- startRendering();
- }
-}
-
-void Mandelbrot::startRendering(const QPointF& renderFirst)
-{
- abortRendering();
- if(m_image->size() != boundingRect().size()) {
- delete m_image;
- m_image = new QImage(width(), height(), MANDELBROT_QIMAGE_FORMAT);
- QPainter(m_image).fillRect(m_image->rect(), Qt::black);
- }
- m_imageIsReady = false;
- m_tilesFinishedRendering = 0;
- m_tiling.start(renderFirst);
- computeStats();
- // abort if required
- if(abortRenderingAsSoonAsPossible()) return;
- for(int i = 0; i < renderThreadCount(); i++) {
- renderThread(i)->start(QThread::LowestPriority);
- }
-}
-
-void Mandelbrot::translateView(const QPointF& _delta)
-{
- abortRendering();
-
- // Compute the new complex coordinate of the viewpoint
- m_center -= resolution() * _delta;
-
- // now translate part the old image and merge it immediately into m_image to give the user a sense of speed
- QPoint delta((int)_delta.x(), (int)_delta.y());
- int srcx = delta.x()>0 ? 0 : -delta.x(),
- srcy = delta.y()>0 ? 0 : -delta.y(),
- dstx = delta.x()>0 ? delta.x() : 0,
- dsty = delta.y()>0 ? delta.y() : 0,
- w = m_image->width() - qAbs(delta.x()),
- h = m_image->height() - qAbs(delta.y());
- QImage part = m_image->copy(srcx,srcy,w,h);
- m_image->fill(0);
- QPainter(m_image).drawImage(QPointF(dstx,dsty), part);
- update(m_image->rect());
-
- // compute which pixel to render first, so we start with the tiles the user is most interested in
- qreal renderfirstx, renderfirsty;
- if(delta.y()!=0 && qAbs(_delta.x()/_delta.y())<qAbs(qreal(width())/height()))
- {
- if(delta.y()>0)
- {
- renderfirstx = width()/2 - _delta.x() * height() / (2 * _delta.y());
- renderfirsty = 0.;
- }
- else
- {
- renderfirstx = width()/2 + _delta.x() * height() / (2 * _delta.y());
- renderfirsty = height();
- }
- }
- else
- {
- if(delta.x()>0)
- {
- renderfirsty = height()/2 - _delta.y() * width() / (2 * _delta.x());
- renderfirstx = 0.;
- }
- else
- {
- renderfirsty = height()/2 + _delta.y() * width() / (2 * _delta.x());
- renderfirstx = width();
- }
- }
- startRendering(QPointF(renderfirstx, renderfirsty));
-}
-
-void Mandelbrot::zoomView(const QPointF& at, qreal zoomFactor)
-{
- abortRendering();
-
- // Compute the new complex coordinate of the viewpoint
- qreal oldResolution = resolution();
- if(zoomFactor < 0.5) zoomFactor = 0.5;
- if(zoomFactor > 2) zoomFactor = 2;
- qreal newzoom = m_zoom * zoomFactor;
- if(newzoom>10.) newzoom = 10.;
- zoomFactor = newzoom/m_zoom;
- m_zoom = newzoom;
- qreal newResolution = resolution();
- m_center += (oldResolution - newResolution) * (at - QPointF(width()/2, height()/2));
-
- // now scale part the old image and merge it immediately into m_image to give the user a sense of speed
- qreal srcwidth = width() * qMin(zoomFactor,(qreal)(1.0));
- qreal srcheight = height() * qMin(zoomFactor,(qreal)(1.0));
- qreal srcleft = at.x() - srcwidth/2.;
- qreal srcright = at.x() + srcwidth/2.;
- qreal srctop = at.y() - srcheight/2.;
- qreal srcbottom = at.y() + srcheight/2.;
- qreal srcleft_c = CLAMP(srcleft, (qreal)(0.0), (qreal)width());
- qreal srcright_c = CLAMP(srcright, (qreal)(0.0), (qreal)width());
- qreal srctop_c = CLAMP(srctop, (qreal)(0.0), (qreal)height());
- qreal srcbottom_c = CLAMP(srcbottom, (qreal)(0.0), (qreal)height());
- qreal srcwidth_c = srcright_c - srcleft_c;
- qreal srcheight_c = srcbottom_c - srctop_c;
- qreal dstwidth = width() * qMin(1./zoomFactor,1.);
- qreal dstheight = height() * qMin(1./zoomFactor,1.);
- qreal dstleft = at.x() - dstwidth/2.;
- qreal dsttop = at.y() - dstheight/2.;
- QImage part(srcwidth, srcheight, m_image->format());
- if(zoomFactor>1.) part.fill(0);
- QPainter(&part).drawImage(QPointF(srcleft_c-srcleft, srctop_c-srctop), *m_image, QRectF(srcleft_c,srctop_c,srcwidth_c,srcheight_c));
- if(zoomFactor>1.) m_image->fill(0);
- QImage scaled = part.scaled(dstwidth, dstheight);
- QPainter(m_image)
- .drawImage(QPointF(dstleft, dsttop),
- scaled);
- update(m_image->rect());
-
- startRendering(at);
-}
-
-int Mandelbrot::maxIter() const
-{
- int max_iter_factor;
- if(quality() == 0) max_iter_factor=100;
- else if(quality() == 1) max_iter_factor=250;
- else max_iter_factor=1000;
- return int(max_iter_factor * -std::log(resolution()));
-}
-
-int Mandelbrot::supersampling() const
-{
- if(quality() <= 2) return 1;
- else if(quality() == 3) return 2;
- else return 4;
-}
-
-QString Mandelbrot::key() const
-{
- // number of guaranteed significant digits in a qreal
- // beware: a too high number of digits will result in inconsistent keys and stale/not-found cached images,
- // while a too low number of digits will result in loading mismatching cached images (actually the latter is
- // almost impossible to avoid when the view is very close to machine precision limits, but that is probably
- // not a big problem).
- const int digits = (sizeof(qreal) >= 8) ? 15 : 6;
- // QString::number doesn't honor any locale setting, that's good for us. The Qt documentation doesn't say
- // whether that's also the case of arg() so let's play safe and use QString::number.
- // notice how we separate the numbers by a space. That prevents "12 3" giving the same key as "1 23".
- QString s = QString(QLatin1String( "%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15" ))
- .arg(QString::number(m_center.x(), 'g', digits))
- .arg(QString::number(m_center.y(), 'g', digits))
- .arg(QString::number(m_zoom, 'g', digits))
- .arg(m_quality).arg(width()).arg(height())
- .arg(m_color1.red()).arg(m_color1.green()).arg(m_color1.blue())
- .arg(m_color2.red()).arg(m_color2.green()).arg(m_color2.blue())
- .arg(m_color3.red()).arg(m_color3.green()).arg(m_color3.blue());
- return QString(QLatin1String( "mandelbrot-%1" )).arg(qHash(s));
-}
-
-void Mandelbrot::computeStats()
-{
- if (height() < 1 || width() < 1) {
- return;
- }
-
- // run a little simulation on 15x15 samples to estimate roughly the minimum iteration count before divergence.
- // This number, m_min_iter_divergence, will be used to tune gradients.
- int max_iter = maxIter();
- m_min_iter_divergence = max_iter;
- for(int i = -7; i < 8; i++) for(int j = -7; j < 8; j++)
- {
- if(m_abortRenderingAsSoonAsPossible) return;
- qreal x_start = center().x() + i * zoom() / 8;
- qreal y_start = center().y() + i * (zoom() * height()/width()) / 8;
- qreal x = x_start;
- qreal y = y_start;
- int iter = 0;
- bool diverged = false;
- do {
- qreal tmp = (x*x - y*y + x_start);
- y = (2*x*y + y_start);
- x = tmp;
- if((x*x + y*y) > 4) diverged = true;
- else iter++;
- } while(iter < max_iter && !diverged);
- if(iter < m_min_iter_divergence) m_min_iter_divergence = iter;
- }
- if(m_min_iter_divergence < 1) m_min_iter_divergence = 1;
-}
-
-void Mandelbrot::tileDone(const MandelbrotTile& t)
-{
- emit update(QRectF(t.destination()).translated(boundingRect().topLeft()));
- m_tilesFinishedRendering++;
- if(m_tilesFinishedRendering >= TILING_SIZE*TILING_SIZE) m_imageIsReady = true;
-}
-
-void Mandelbrot::exportImage()
-{
- KUrl url = KFileDialog::getSaveUrl(
- KUrl(),
- QLatin1String( "*.png|" )+i18n( "PNG images" ),
- 0,
- QString(),
- KFileDialog::ConfirmOverwrite
- );
- QByteArray ba;
- QBuffer buffer(&ba);
- buffer.open(QIODevice::WriteOnly);
- m_image->save(&buffer, "PNG");
- KIO::file_delete(url);
- KIO::storedPut(ba, url, -1);
-}
-
-void Mandelbrot::exportConfig()
-{
- QString file = KFileDialog::getSaveFileName(
- KUrl(),
- QLatin1String( "*.txt|" )+i18n( "Text files" ),
- 0,
- QString(),
- KFileDialog::ConfirmOverwrite
- );
- KConfig config(file, KConfig::SimpleConfig);
- KConfigGroup configgroup(&config, "Mandelbrot");
- save(configgroup);
- configgroup.config()->sync();
-}
-
-void Mandelbrot::importConfig()
-{
- QString file = KFileDialog::getOpenFileName(
- KUrl(),
- QLatin1String( "*.txt|" )+i18n( "Text files" ),
- 0,
- QString()
- );
- if(file.isEmpty()) return;
- KConfig config(file, KConfig::SimpleConfig);
- KConfigGroup configgroup(&config, "Mandelbrot");
- readConfig(configgroup, ReadViewpoint); // reading colors and quality level is implicit
-} // but we dont want to read the lock status
-
-#include "moc_mandelbrot.cpp"
+++ /dev/null
-// Copyright 2008-2009 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-#ifndef MANDELBROT_HEADER
-#define MANDELBROT_HEADER
-
-#include <QColor>
-#include <QRect>
-#include <QPainter>
-#include <plasma/wallpaper.h>
-
-#include "ui_config.h"
-
-#include "global.h"
-#include "tile.h"
-#include "renderthread.h"
-
-/** A Plasma Wallpaper that displays and allows to navigate through the Mandelbrot set
- *
- * The rendering is done in a separate MandelbrotRenderThread class. However the present Mandelbrot
- * class serves as a central repository of data that is shared between all threads. Whence all the
- * byzantine data members here. Definitely not very clean, but works, and this is just application code, right?
- */
-class Mandelbrot : public Plasma::Wallpaper
-{
- Q_OBJECT
-
-#ifdef MANDELBROT_KEEP_KDE44_COMPATIBILITY
- inline bool isPreviewing() { return width()*height()<100000; }
-#endif
-
- public:
- Mandelbrot(QObject* parent, const QVariantList& args);
- ~Mandelbrot();
-
- /** saves the config and updates the image cache. called by plasma. \see Plasma::Wallpaper*/
- virtual void save(KConfigGroup &config);
- /** \see Plasma::Wallpaper */
- virtual void paint(QPainter* painter, const QRectF& exposedRect);
- /** \see Plasma::Wallpaper */
- virtual QWidget* createConfigurationInterface(QWidget* parent);
- /** \returns the width of the wallpaper in pixels */
- int width() const { return (int)boundingRect().width(); }
- /** \returns the height of the wallpaper in pixels */
- int height() const { return (int)boundingRect().height(); }
- /** \returns the complex coordinate of the center of the viewpoint \see m_center */
- const QPointF& center() const { return m_center; }
- /** \returns the half-width of the view in the complex plane \see m_zoom */
- const qreal& zoom() const { return m_zoom; }
- /** \returns the image of the wallpaper \see m_image */
- QImage *image() { return m_image; }
- /** \returns the first color of the gradient, a.k.a. the inside color \see m_color1 */
- const QColor& color1() const { return m_color1; }
- /** \returns the second color of the gradient, a.k.a. the frontier color \see m_color2 */
- const QColor& color2() const { return m_color2; }
- /** \returns the third color of the gradient, a.k.a. the outside color \see m_color3 */
- const QColor& color3() const { return m_color3; }
- /** \returns the quality level as set by the KComboBox in the UI. \see m_quality */
- int quality() const { return m_quality; }
- /** \returns true is the view is locked (as set in the UI in the corresponding checkbox) \see m_lock */
- bool lock() const { return m_lock; }
-
- /** \returns a reference to the current tiling state being rendered \see m_tiling*/
- MandelbrotTiling& tiling() { return m_tiling; }
- /** \returns the number of rendering threads \see m_renderThreadCount */
- int renderThreadCount() const { return m_renderThreadCount; }
- /** \returns a pointer to the i-th rendering thread \see m_renderThreads*/
- MandelbrotRenderThread *renderThread(int i) { return m_renderThreads[i]; }
- /** \returns the distance in the complex plane between two adjacent pixels. So a smaller value of resolution() means a
- * closer zoom. \see zoom(), m_zoom
- */
- qreal resolution() const { return 2*zoom()/width(); }
- /** \returns a statistical estimation of the minimum count of iterations before divergence, as estimated from a few samples.
- * \note this functions only returns the precomputed result. You need to ask explicitly for it to be computed beforehand,
- * by calling computeStats() */
- int min_iter_divergence() const { return m_min_iter_divergence; }
- /** \returns true if the host CPU has SSE2 instructions */
- bool hasSSE2() const { return m_hasSSE2; }
- /** \returns true if rendering should be aborted as soon as possible */
- bool abortRenderingAsSoonAsPossible() const { return m_abortRenderingAsSoonAsPossible; }
- /** \returns the maximum number of iterations to try before declaring non-divergence */
- int maxIter() const;
- /** \returns 1 for no supersampling, 2 for 4x (2x2) supersampling, 4 for 16x (4x4) supersampling, etc... */
- int supersampling() const;
- /** \returns a key based on a hash of all the parameters that influence rendering. So if keys agree, the resulting images
- * can safely be assumed to also agree. */
- QString key() const;
- /** computes the stats, that is currently m_min_iter_before_divergence. \see min_iter_divergence() */
- void computeStats();
- /** sets the value of m_imageIsReady. \see m_imageIsReady */
- void setImageIsReady(bool b) { m_imageIsReady = b; }
-
- signals:
- /** Signals that the configuration has changed */
- void settingsChanged(bool);
-
- public slots:
- /** To be called whenever the given tile is done rendering */
- void tileDone(const MandelbrotTile& t);
-
- void exportImage();
- void exportConfig();
- void importConfig();
-
- protected:
- virtual void init(const KConfigGroup &config);
- virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
- virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
- virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
- virtual void wheelEvent(QGraphicsSceneWheelEvent *event);
-
- /** (re-)starts rendering.
- * \param renderFirst pixel in the image that the user is most interested in. The nearest tiles will be rendered first.
- */
- void startRendering(const QPointF& renderFirst);
- /** convenience overloaded function, starts from the middle of the image. For restarting, call abortRendering() beforehand. */
- void startRendering() { startRendering(QPointF(width()/2,height()/2)); }
- /** self-explanatory. For restarting, call abortRendering() beforehand. */
- void loadFromCacheOrStartRendering();
- /** self-explanatory */
- void abortRendering();
-
- /** \param delta the translation, in pixels */
- void translateView(const QPointF& delta);
- /** \param at the pixel to zoom to/from
- * \param zoomFactor smaller than 1 for zoom in, bigger than 1 for zoom out */
- void zoomView(const QPointF& at, qreal zoomFactor);
-
- /** removes the current cache entry if it is obsolete, and inserts the new image into cache if it is ready */
- void updateCache();
-
- enum { ReadViewpoint=0x1, ReadLockStatus=0x2 };
- void readConfig(const KConfigGroup &config, int options);
-
- protected slots:
- void setColor1(const QColor& color1);
- void setColor2(const QColor& color2);
- void setColor3(const QColor& color3);
- void setQuality(int quality);
- void setLock(int lock);
- void checkRenderHints();
-
- private:
- Ui::Config m_ui;
- QColor m_color1, m_color2, m_color3;
- int m_quality;
- Qt::CheckState m_lock;
- QImage *m_image;
- MandelbrotTiling m_tiling;
- QPointF m_center;
- qreal m_zoom;
- MandelbrotRenderThread **m_renderThreads;
- int m_renderThreadCount;
- QPointF m_mousePressPos, m_mouseLastMovePos;
- Qt::MouseButtons m_mousePressedButtons;
- int m_min_iter_divergence;
- QString m_cacheKey;
- int m_tilesFinishedRendering;
- QAction m_exportImageAction;
- QAction m_exportConfigAction;
- QAction m_importConfigAction;
- bool m_abortRenderingAsSoonAsPossible : 1;
- bool m_hasSSE2 : 1;
- bool m_imageIsReady : 1;
- bool m_firstInit : 1;
-};
-
-#endif
+++ /dev/null
-// Copyright 2008-2009 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#include "mix.h"
-
-/** \returns a RGB mix two floating-point colors of which both RGB and HSV representations are known. The coefficient s is in the range [0,1].
- */
-Color3 mix(const Color3& a_rgb, const Color3& a_hsv, const Color3& b_rgb, const Color3& b_hsv, qreal s)
-{
- if(a_hsv[2] < qreal(0.4) * b_hsv[2]
- || b_hsv[2] < qreal(0.4) * a_hsv[2]
- || a_hsv[1] < qreal(0.4) * b_hsv[1]
- || b_hsv[1] < qreal(0.4) * a_hsv[1])
- {
- // prefer RGB mixing
- return a_rgb*s+b_rgb*(qreal(1)-s);
- }
- else
- {
- // prefer HSV mixing
- Color3 a_hsv_corrected = a_hsv;
- if(a_hsv_corrected[0] - b_hsv[0] > qreal(0.5)) a_hsv_corrected[0] -= qreal(1);
- if(a_hsv_corrected[0] - b_hsv[0] < qreal(-0.5)) a_hsv_corrected[0] += qreal(1);
- Color3 result_hsv = a_hsv_corrected*s + b_hsv*(qreal(1)-s);
- if(result_hsv[0]<qreal(0)) result_hsv[0]+=qreal(1);
- if(result_hsv[0]>qreal(1)) result_hsv[0]-=qreal(1);
- Color3 result_rgb;
- QColor::fromHsvF(result_hsv[0], result_hsv[1], result_hsv[2])
- .getRgbF(&result_rgb[0], &result_rgb[1], &result_rgb[2]);
- return result_rgb;
- }
-}
-
-unsigned char qreal_to_uchar_color_channel(qreal t)
-{
- qreal t_scaled = qreal(255)*t;
- qreal floor_t_scaled = std::floor(t_scaled);
- qreal probability_to_add_one = t_scaled - floor_t_scaled;
- // note: qrand() is thread-safe, std::rand() isn't.
- qreal result = floor_t_scaled + (qrand() < int(qreal(RAND_MAX)*probability_to_add_one) ? qreal(1) : qreal(0));
- int result_int_clamped = (int) CLAMP(result, qreal(0), qreal(255));
- return (unsigned char) result_int_clamped;
-}
+++ /dev/null
-// Copyright 2008-2009 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef MIX_HEADER
-#define MIX_HEADER
-
-#include "mandelbrot.h"
-#include <Eigen/Core>
-
-typedef Eigen::Matrix<qreal,3,1> Color3;
-Color3 mix(const Color3& a_rgb, const Color3& a_hsv, const Color3& b_rgb, const Color3& b_hsv, qreal s);
-unsigned char qreal_to_uchar_color_channel(qreal t);
-
-#endif // MIX_HEADER
+++ /dev/null
-[Desktop Entry]
-Name=Mandelbrot
-Name[ar]=Mandelbrot
-Name[ast]=Mandelbrot
-Name[bs]=Mandelbrot
-Name[ca]=Mandelbrot
-Name[ca@valencia]=Mandelbrot
-Name[cs]=Mandelbrot
-Name[da]=Mandelbrot
-Name[de]=Mandelbrot
-Name[el]=Mandelbrot
-Name[en_GB]=Mandelbrot
-Name[eo]=Mandelbrot
-Name[es]=Mandelbrot
-Name[et]=Mandelbrot
-Name[fi]=Mandelbrot
-Name[fr]=Mandelbrot
-Name[ga]=Mandelbrot
-Name[gl]=Mandelbrot
-Name[hr]=Mandelbrot
-Name[hu]=Mandelbrot
-Name[is]=Mandelbrot
-Name[it]=Mandelbrot
-Name[ja]=マンデルブロ
-Name[kk]=Мандельброт
-Name[km]=Mandelbrot
-Name[ko]=만델브로
-Name[lt]=Mandelbrotas
-Name[lv]=Mandelbrot
-Name[mr]=मेन्डलब्रोट
-Name[nb]=Mandelbrot
-Name[nds]=Appelmanntje
-Name[nl]=Mandelbrot
-Name[nn]=Mandelbrot
-Name[pa]=ਮੈਨਡਲਬਰਾਟ
-Name[pl]=Mandelbrot
-Name[pt]=Mandelbrot
-Name[pt_BR]=Mandelbrot
-Name[ro]=Mandelbrot
-Name[ru]=Множество Мандельброта
-Name[sk]=Mandelbrot
-Name[sl]=Mandelbrot
-Name[sq]=Mandelbrot
-Name[sr]=Манделброт
-Name[sr@ijekavian]=Манделброт
-Name[sr@ijekavianlatin]=Mandelbrot
-Name[sr@latin]=Mandelbrot
-Name[sv]=Mandelbrot
-Name[tr]=Mandelbrot
-Name[uk]=Мандельброт
-Name[wa]=Mandelbrot
-Name[x-test]=xxMandelbrotxx
-Name[zh_CN]=Mandelbrot
-Name[zh_TW]=Mandelbrot
-Comment=Explore a classic fractal design
-Comment[bs]=Istražite klasični fraktalni dizajn
-Comment[ca]=Explora un disseny fractal clàssic
-Comment[ca@valencia]=Explora un disseny fractal clàssic
-Comment[cs]=Prozkoumávejte návrh klasického fraktálu
-Comment[da]=Udforsk et klassisk brøkdesign
-Comment[de]=Klassisches Fraktalbild erkunden
-Comment[el]=Εξερεύνηση ενός κλασικού μορφοκλασματικού σχεδίου
-Comment[en_GB]=Explore a classic fractal design
-Comment[es]=Explorar un diseño fractal clásico
-Comment[et]=Klassikalise fraktalikujundi esitamine
-Comment[fi]=Tutki klassista fraktaalimuotoa
-Comment[fr]=Explorer une conception classique fractale
-Comment[gl]=Explore un deseño fractal clásico.
-Comment[hu]=Klasszikus fraktálterv felfedezése
-Comment[it]=Esplora un disegno frattale classico
-Comment[kk]=Классикалық фрактал құрылымын зертттеу
-Comment[ko]=고전 프랙탈 디자인 감상
-Comment[nb]=Utforsk en klassisk fraktalfigur
-Comment[nds]=En klass'sch Fraktaalbild belackschaun
-Comment[nl]=Verken het klassieke ontwerpen van een fractal
-Comment[pl]=Poznaj klasyczne projektowanie fraktali
-Comment[pt]=Explorar um desenho de fractal clássico
-Comment[pt_BR]=Explora um desenho de fractal clássico
-Comment[ru]=Исследование классического фрактала
-Comment[sk]=Preskúmať klasický fraktálový dizajn
-Comment[sl]=Raziščite klasične fraktale
-Comment[sr]=Истражите класични фрактални образац
-Comment[sr@ijekavian]=Истражите класични фрактални образац
-Comment[sr@ijekavianlatin]=Istražite klasični fraktalni obrazac
-Comment[sr@latin]=Istražite klasični fraktalni obrazac
-Comment[sv]=Utforska en klassisk fraktal
-Comment[tr]=Klasik bir fraktal tasarım keşfedin
-Comment[uk]=Вивчення структури класичного фрактала
-Comment[x-test]=xxExplore a classic fractal designxx
-Comment[zh_CN]=探索经典分形设计
-Comment[zh_TW]=探索傳統的拼布設計
-Type=Service
-Icon=preferences-desktop-mandelbrot
-ServiceTypes=Plasma/Wallpaper
-
-X-KDE-Library=plasma_wallpaper_mandelbrot
-X-KDE-PluginInfo-Author=Benoît Jacob
-X-KDE-PluginInfo-Email=jacob.benoit.1@gmail.com
-X-KDE-PluginInfo-Name=mandelbrot
-X-KDE-PluginInfo-Version=pre0.1
-X-KDE-PluginInfo-Website=http://plasma.kde.org/
-X-KDE-PluginInfo-Depends=
-X-KDE-PluginInfo-License=GPL
-X-KDE-PluginInfo-EnabledByDefault=true
-
+++ /dev/null
-// Copyright 2008-2009 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef RENDER_HEADER
-#define RENDER_HEADER
-
-namespace with_arch_defaults
-{
-#include "render_impl.h"
-}
-
-namespace with_SSE2_explicitly_enabled_if_x86
-{
-#include "render_impl.h"
-}
-
-#endif // RENDER_HEADER
+++ /dev/null
-// Copyright 2008-2010 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#include "mandelbrot.h"
-#include "mix.h"
-#include <Eigen/Array>
-#include <limits>
-
-#ifdef THIS_PATH_WITH_SSE2_EXPLICTLY_ENABLED
-namespace with_SSE2_explicitly_enabled_if_x86 {
-#else
-namespace with_arch_defaults {
-#endif
-
-/* The number of iterations to do before testing for divergence. The higher, the faster. However,
- * at each iteration we square z, and z may initially have modulus up to 2. So we're very quickly hitting the
- * exponent limit of floating point numbers. Taking into account that we want this number to be a multiple of 4,
- * as we are going to peel the inner loop by 4, the values below are the largest possible.
- * As they are so small, we make them compile-time constants to allow to compiler to unroll if it decides to.
- */
-template<typename T> struct iter_before_test { enum { ret = 4 }; };
-template<> struct iter_before_test<double> { enum { ret = 8 }; };
-
-template<typename Real>
-struct mandelbrot_render_tile_impl
-{
- // number of reals in a SIMD packet.
- // Examples:
- // * no vectorization: then packet_size == 1 always
- // * SSE or AltiVec: then packet_size is 4 if Real==float and is 2 if Real==double
- enum { packet_size = Eigen::ei_packet_traits<Real>::size };
-
- // with Eigen, if we use vectors of the right size, operations on them will be compiled
- // as operations on SIMD packets
- typedef Eigen::Matrix<Real, packet_size, 1> Packet;
- typedef Eigen::Matrix<int, packet_size, 1> Packeti;
-
- // normally we wouldn't need to do that, but since some compilers can miss optimizations,
- // in the most critical code, let's play directly with SIMD registers. It's completely equivalent
- // to Eigen vectors of the right size, just less subtle for the compiler to get right.
- typedef typename Eigen::ei_packet_traits<Real>::type LowlevelPacket;
-
- // how many iterations we do before testing for divergence. See comment above for struct iter_before_test.
- // must be a multiple of 4 as we'll peel the inner loop by 4
- enum { iter_before_test = iter_before_test<Real>::ret };
-
- Real resolution;
- int supersampling;
- int max_iter;
- float log_max_iter;
- float tmin;
- float log_of_2;
- float log_of_2log2;
- Real square_bailout_radius, log_log_square_bailout_radius;
- Color3 rgb1, rgb2, rgb3, hsv1, hsv2, hsv3;
- Mandelbrot *mandelbrot;
- QImage *image;
- const MandelbrotTile& tile;
- bool found_exterior_point;
-
- mandelbrot_render_tile_impl(Mandelbrot *m, const MandelbrotTile& t)
- : mandelbrot(m), tile(t) { init(); }
- void init();
- void computePacket(int x, int y, Color3 *pixels);
-};
-
-template<typename Real>
-void mandelbrot_render_tile_impl<Real>::init()
-{
- // remember if we already rendered some exterior point. will be useful for the check for fully interior tiles
- found_exterior_point = false;
-
- // the supersampling factor.
- supersampling = mandelbrot->supersampling();
-
- // the resolution, i.e. the distance in the complex plane between adjacent pixels.
- resolution = Real(mandelbrot->resolution()) / supersampling;
-
- /***************
- Henceforth, we can completely forget about supersampling -- it's implicit.
- Supersampling only means that 'image' is bigger and 'resolution' is smaller than they would otherwise be,
- but from now on we don't need to care.
- ***************/
-
- // how many iterations we do on each sample before declaring that it doesn't diverge
- max_iter = mandelbrot->maxIter();
-
- // precompute some constants that will be used in the coloring computations
- log_max_iter = std::log(float(max_iter));
- if(mandelbrot->min_iter_divergence() != 0 && mandelbrot->min_iter_divergence() != max_iter)
- {
- tmin = std::log(float(mandelbrot->min_iter_divergence())) / log_max_iter;
- }
- else tmin = 0.f;
-
- square_bailout_radius = 20; // value found in papers on continuous escape time formulas, changing it can degrade the smoothness.
- log_log_square_bailout_radius = std::log(std::log(square_bailout_radius));
-
- log_of_2 = std::log(2.f);
- log_of_2log2 = std::log(2.f*log_of_2);
-
- mandelbrot->color1().getRgbF(&rgb1[0], &rgb1[1], &rgb1[2]);
- mandelbrot->color1().getHsvF(&hsv1[0], &hsv1[1], &hsv1[2]);
- mandelbrot->color2().getRgbF(&rgb2[0], &rgb2[1], &rgb2[2]);
- mandelbrot->color2().getHsvF(&hsv2[0], &hsv2[1], &hsv2[2]);
- mandelbrot->color3().getRgbF(&rgb3[0], &rgb3[1], &rgb3[2]);
- mandelbrot->color3().getHsvF(&hsv3[0], &hsv3[1], &hsv3[2]);
-}
-
-template<typename Real>
-void mandelbrot_render_tile_impl<Real>::computePacket(int x, int y, Color3 *pixels)
-{
- // for each pixel, we're going to do the iteration z := z^2 + c where z and c are complex numbers,
- // starting with z = c = complex coord of the pixel. pzr and pzi denote the real and imaginary parts of z.
- // pcr and pci denote the real and imaginary parts of c.
- Packet pcr, pci, pzr, pzi, pzr_buf;
-
- for(int i = 0; i < packet_size; i++) {
- pzi[i] = pci[i] = tile.affix().y() + y * resolution;
- pzr[i] = pcr[i] = tile.affix().x() + (x+i) * resolution;
- }
-
- /* first step: do iterations by batches of 'iter_before_test'. Testing only every 'iter_before_test'
- * iterations allows to go faster.
- */
- int j = 0;
- Packet pzabs2;
- Packeti pixel_iter = Packeti::Zero(), // number of iteration per pixel in the packet
- pixel_diverge = Packeti::Zero(); // whether or not each pixel has already diverged
- int count_not_yet_diverged = packet_size;
-
- Packet pzr_previous, pzi_previous,
- pzr_before_diverge = Packet::Zero(), pzi_before_diverge = Packet::Zero();
- do
- {
- pzr_previous = pzr;
- pzi_previous = pzi;
-
- /* perform iter_before_test iterations */
- for(int i = 0; i < iter_before_test/4; i++) // we peel the inner loop by 4
- {
- LowlevelPacket lpzr, lpzi;
- for(int repeat = 0; repeat < 4; repeat++)
- {
- lpzr = Eigen::ei_pload(pzr.data());
- lpzi = Eigen::ei_pload(pzi.data());
- Eigen::ei_pstore(pzr.data(),
- Eigen::ei_padd(
- Eigen::ei_psub(
- Eigen::ei_pmul(lpzr,lpzr),
- Eigen::ei_pmul(lpzi,lpzi)
- ),
- Eigen::ei_pload(pcr.data())
- )
- );
- Eigen::ei_pstore(pzi.data(),
- Eigen::ei_padd(
- Eigen::ei_pmul(
- Eigen::ei_padd(lpzr,lpzr),
- lpzi
- ),
- Eigen::ei_pload(pci.data())
- )
- );
- }
- }
-
- /* test for divergence */
- pzabs2 = pzr.cwise().square();
- pzabs2 += pzi.cwise().square();
- for(int i = 0; i < packet_size; i++) {
- if(!(pixel_diverge[i])) {
- if(pzabs2[i] > square_bailout_radius) {
- pixel_diverge[i] = 1;
- pzr_before_diverge[i] = pzr_previous[i];
- pzi_before_diverge[i] = pzi_previous[i];
- count_not_yet_diverged--;
- }
- else pixel_iter[i] += iter_before_test;
- }
- }
-
- j += iter_before_test;
- }
- while(j < max_iter && count_not_yet_diverged);
-
- /* Second step: we know the iteration count before divergence for each pixel but only up to precision
- * 'iter_before_test'. We now want to get the exact iteration count before divergence,
- * so we iterate again starting from where we were before divergence, and now we test at every iteration.
- */
- j = 0;
- pzr = pzr_before_diverge;
- pzi = pzi_before_diverge;
- pixel_diverge = Packeti::Zero();
- count_not_yet_diverged = packet_size;
- typedef Eigen::Matrix<float,packet_size,1> Packet_to_float;
- Packet_to_float square_escape_modulus = Packet_to_float::Zero();
- do
- {
- pzr_buf = pzr;
- pzr = pzr.cwise().square();
- pzr -= pzi.cwise().square();
- pzr += pcr;
- pzi = (2*pzr_buf).cwise()*pzi;
- pzi += pci;
- pzabs2 = pzr.cwise().square();
- pzabs2 += pzi.cwise().square();
- for(int i = 0; i < packet_size; i++) {
- if(!(pixel_diverge[i])) {
- if(pzabs2[i] > square_bailout_radius) {
- pixel_diverge[i] = 1;
- square_escape_modulus[i] = (float)pzabs2[i];
- count_not_yet_diverged--;
- }
- else pixel_iter[i]++;
- }
- }
- j++;
- }
- while(j < iter_before_test && count_not_yet_diverged);
-
- if(count_not_yet_diverged < packet_size) found_exterior_point = true;
-
- /* Now we know exactly the number of iterations before divergence, and the escape modulus. */
-
- /* Third step: compute pixel colors. */
-
- for(int i = 0; i < packet_size; i++)
- {
- Real log_log_escape_modulus = Real(0);
- if(square_escape_modulus[i] > Real(1))
- {
- Real log_escape_modulus = std::log(square_escape_modulus[i]);
- if(log_escape_modulus > Real(1))
- log_log_escape_modulus = std::log(log_escape_modulus);
- }
- Real normalized_iter_count = pixel_iter[i] + (log_log_square_bailout_radius - log_log_escape_modulus) / log_of_2;
- Real log_normalized_iter_count = (normalized_iter_count > Real(1)) ? std::log(normalized_iter_count) : Real(0);
- Real t = log_normalized_iter_count / log_max_iter;
-
- // Now, remember that we did a little statistical analysis on some samples
- // to determine roughly what would be the smallest count of iterations before divergence.
- // At the beginning of the present function, we used that to compute 'tmin'.
- // Now we use it to make the gradient actually start at t=tmin. Lower values of t just give black.
- // In other words, we are ensuring that no matter what the viewpoint, the darkest part of the image
- // will always be black (at least if our statistical analysis went well).
- // In other words, we are trying to get optimal contrast. This is important as otherwise there could be
- // almost no contrast at all and an interesting viewpoint could give an almost blank image.
- t = (t-tmin)/(1.f-tmin);
- t = CLAMP(t, Real(0), Real(1));
-
- float threshold1 = 0.09f;
- float threshold2 = 0.3f;
- if(t < threshold1) {
- pixels[i] = (t/threshold1)*rgb3;
- }
- else if(t < threshold2) {
- pixels[i] = mix(rgb2, hsv2, rgb3, hsv3, (t - threshold1) / (threshold2 - threshold1));
- }
- else {
- pixels[i] = mix(rgb1, hsv1, rgb2, hsv2, (t - threshold2) / (1.f - threshold2));
- }
- }
-}
-
-
-/** This is the main rendering function. It renders only the current tile of the Mandelbrot wallpaper.
- *
- * The image parameter is the image to render the tile to. The size of this image determines how many pixels we render.
- * So to get supersampled rendering, just pass a larger image here, and then scale it down to the real size using smooth
- * scaling.
- *
- * This function only writes to 'image', it does not at all write to mandelbrot->image() directly. The mandelbrot parameter
- * is only used to determine the parameters of the rendering such as viewpoint, colors, etc.
- */
-template<typename Real> void mandelbrot_render_tile(
- Mandelbrot *mandelbrot,
- const MandelbrotTile& tile
-)
-{
-// if we're compiling the path with SSE2 explicitly enabled, since it's only used on x86 (and not even on x86-64 since it has SSE2 by
-// default), let's only compile the code if it's going to be used!
-
-#if defined(HAVE_PATH_WITH_SSE2_EXPLICTLY_ENABLED) || !defined(THIS_PATH_WITH_SSE2_EXPLICTLY_ENABLED)
-
- enum { packet_size = Eigen::ei_packet_traits<Real>::size };
- Color3 dummy_buffer[packet_size];
-
- mandelbrot_render_tile_impl<Real> renderer(mandelbrot, tile);
-
- int supersampling = renderer.supersampling;
- int supersampled_packet_size = supersampling * packet_size;
- int tile_x = tile.destination().x();
- int tile_y = tile.destination().y();
- int tile_width = tile.destination().width();
- int tile_height = tile.destination().height();
- int supersampled_tile_width = supersampling * tile_width;
- int supersampled_tile_height = supersampling * tile_height;
-
- // first render a part of the border to check if the tile is probably entirely inside the interior of the Mandelbrot set
- for(int y = 1; y < supersampled_tile_height-1; y+=4) // render every 4th pixel on the border
- {
- renderer.computePacket(0,y,dummy_buffer);
- renderer.computePacket(supersampled_tile_width - packet_size, y, dummy_buffer);
- // abort if required
- if(mandelbrot->abortRenderingAsSoonAsPossible()) return;
- }
- for(int x = 0; x < supersampled_tile_width; x+= 4*packet_size)
- {
- renderer.computePacket(x,0,dummy_buffer);
- renderer.computePacket(x,supersampled_tile_height-1,dummy_buffer);
- // abort if required
- if(mandelbrot->abortRenderingAsSoonAsPossible()) return;
- }
- // render the bottom-right packet: due to our rendering only every 4-th packet on the border, we could be
- // missing this corner of the tile.
- renderer.computePacket(supersampled_tile_width-packet_size,supersampled_tile_height-1,dummy_buffer);
-
- // now, if the tile looks like it's entirely inside the interior, just assume that's the case,
- // so fill it (not using a QPainter so as to avoid having to lock a mutex in case the image is being accessed
- // by another QPainter in the GUI thread) and return.
- if(!(renderer.found_exterior_point))
- {
- for(int y = 0; y < tile_height; y++)
- {
- for(int x = 0; x < tile_width; x++)
- {
- unsigned char *pixel
- = const_cast<unsigned char*>(
- static_cast<const QImage *>(mandelbrot->image())->scanLine(tile_y+y)
- ) + 4*(tile_x+x);
- pixel[0] = mandelbrot->color1().blue();
- pixel[1] = mandelbrot->color1().green();
- pixel[2] = mandelbrot->color1().red();
- pixel[3] = 255;
- }
- }
- return;
- }
-
- // ok now do the actual rendering. not much point trying to reuse the part of the border we've already rendered,
- // it's few pixels and it would take some nontrivial code.
-
- qreal one_over_supersampling_squared = qreal(1) / (supersampling*supersampling);
-
- for(int y = 0; y < tile_height; y++)
- {
- for(int x = 0; x < tile_width; x += packet_size)
- {
- Color3 supersampled_buffer[MAX_SUPERSAMPLING][packet_size * MAX_SUPERSAMPLING];
-
- for(int y2 = 0; y2 < supersampling; y2++)
- {
- for(int x2 = 0; x2 < supersampled_packet_size; x2 += packet_size)
- {
- renderer.computePacket(supersampling*x+x2,supersampling*y+y2,&supersampled_buffer[y2][x2]);
- // abort if required
- if(mandelbrot->abortRenderingAsSoonAsPossible()) return;
- }
- }
-
- int pixels_to_write = std::min(int(packet_size), tile_width-x);
- for(int i = 0; i < pixels_to_write; i++)
- {
- Color3 color = Color3::Zero();
- for(int y2 = 0; y2 < supersampling; y2++)
- {
- for(int x2 = 0; x2 < supersampling; x2++)
- {
- color += supersampled_buffer[y2][x2 + i*supersampling];
- }
- }
- color *= one_over_supersampling_squared;
- unsigned char *pixel
- = const_cast<unsigned char*>(
- static_cast<const QImage *>(mandelbrot->image())->scanLine(tile_y+y)
- ) + 4*(tile_x+x+i);
- pixel[0] = qreal_to_uchar_color_channel(color[2]);
- pixel[1] = qreal_to_uchar_color_channel(color[1]);
- pixel[2] = qreal_to_uchar_color_channel(color[0]);
- pixel[3] = 255;
- }
- }
- }
-#else
- Q_UNUSED(mandelbrot);
- Q_UNUSED(tile);
-#endif
-}
-
-template void mandelbrot_render_tile<float>(
- Mandelbrot *mandelbrot,
- const MandelbrotTile& tile
-);
-
-template void mandelbrot_render_tile<double>(
- Mandelbrot *mandelbrot,
- const MandelbrotTile& tile
-);
-
-}
+++ /dev/null
-// Copyright 2008-2009 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-// No header guards should be used here as this file is expected to be
-// #includeable more than once
-//krazy:skip
-
-template<typename Real> void mandelbrot_render_tile(
- Mandelbrot *mandelbrot,
- const MandelbrotTile& tile
-);
+++ /dev/null
-#define THIS_PATH_WITH_SSE2_EXPLICTLY_ENABLED
-#include "render_impl.cpp"
+++ /dev/null
-#include "render_impl.cpp"
+++ /dev/null
-// Copyright 2008-2010 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#include "mandelbrot.h"
-#include "render.h"
-
-MandelbrotRenderThread::MandelbrotRenderThread(Mandelbrot *m) : m_mandelbrot(m)
-{
- connect(this, SIGNAL(tileDone(MandelbrotTile)), m_mandelbrot, SLOT(tileDone(MandelbrotTile)));
-}
-
-void MandelbrotRenderThread::run()
-{
- while(true)
- {
- MandelbrotTile tile;
- if(!m_mandelbrot->tiling().next(&tile)) return;
- QRect destination = tile.destination();
-
- // this is on purpose slightly larger than machine epsilon for float (gave artifacts near the transition point)
- const qreal double_precision_threshold = (qreal)4.0e-07;
- const qreal rendering_resolution = m_mandelbrot->resolution() / m_mandelbrot->supersampling();
-
-#ifdef HAVE_PATH_WITH_SSE2_EXPLICTLY_ENABLED
- if(m_mandelbrot->hasSSE2())
- {
- if(rendering_resolution > double_precision_threshold) {
- with_SSE2_explicitly_enabled_if_x86::mandelbrot_render_tile<float>(m_mandelbrot, tile);
- }
- else {
- with_SSE2_explicitly_enabled_if_x86::mandelbrot_render_tile<double>(m_mandelbrot, tile);
- }
- }
- else
-#endif
- {
- if(rendering_resolution > double_precision_threshold) {
- with_arch_defaults::mandelbrot_render_tile<float>(m_mandelbrot, tile);
- }
- else {
- with_arch_defaults::mandelbrot_render_tile<double>(m_mandelbrot, tile);
- }
- }
-
- // abort if required
- if(m_mandelbrot->abortRenderingAsSoonAsPossible()) return;
-
- // tell the world we've got a shiny new tile
- emit tileDone(tile);
- }
-}
-
-#include "moc_renderthread.cpp"
+++ /dev/null
-// Copyright 2008-2009 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-#ifndef RENDERTHREAD_HEADER
-#define RENDERTHREAD_HEADER
-
-#include <QThread>
-#include "global.h"
-
-class MandelbrotRenderThread : public QThread
-{
- Q_OBJECT
- friend class Mandelbrot;
- Mandelbrot * const m_mandelbrot;
-
- public:
- MandelbrotRenderThread(Mandelbrot *m);
- ~MandelbrotRenderThread() {}
- void run();
-
- signals:
- void tileDone(const MandelbrotTile& t);
-};
-
-#endif
+++ /dev/null
-// Copyright 2008-2009 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#include <QtCore/qmutex.h>
-
-#include "mandelbrot.h"
-
-bool MandelbrotTiling::next(MandelbrotTile *result)
-{
- QMutexLocker locker(&m_mutex);
- int m_square_horiz_dist[TILING_SIZE], m_square_vert_dist[TILING_SIZE];
- for(int i = 0; i < TILING_SIZE; i++) {
- int x = m_renderFirst.x() - int((1/(2*double(TILING_SIZE)) + i/double(TILING_SIZE)) * m_mandelbrot->width());
- m_square_horiz_dist[i] = x*x;
- int y = m_renderFirst.y() - int((1/(2*double(TILING_SIZE)) + i/double(TILING_SIZE)) * m_mandelbrot->height());
- m_square_vert_dist[i] = y*y;
- }
-
- int min_square_distance = INT_MAX;
- int result_x = 0, result_y = 0;
- for(int i = 0; i < TILING_SIZE; i++) for(int j = 0; j < TILING_SIZE; j++) {
- if(m_board[i][j] == 0) {
- int square_distance = m_square_horiz_dist[i] + m_square_vert_dist[j];
- if(square_distance<min_square_distance) {
- result_x = i;
- result_y = j;
- min_square_distance = square_distance;
- }
- }
- }
-
- result->set(m_mandelbrot, result_x, result_y);
- m_board[result->x()][result->y()] = 1;
- m_number++;
-
- return m_number <= TILING_SIZE*TILING_SIZE;
-}
-
-void MandelbrotTiling::start(const QPointF& renderFirst)
-{
- m_number = 0;
- m_renderFirst = QPoint((int)renderFirst.x(), (int)renderFirst.y());
- for(int i = 0; i < TILING_SIZE; i++) for(int j = 0; j < TILING_SIZE; j++) m_board[i][j] = 0;
-}
-
-QPointF MandelbrotTile::affix() const
-{
- return QPointF(m_mandelbrot->center().x() + (-1+2*qreal(m_x)/TILING_SIZE) * m_mandelbrot->zoom(),
- m_mandelbrot->center().y() + (-1+2*qreal(m_y)/TILING_SIZE) * m_mandelbrot->zoom()
- * m_mandelbrot->height() / m_mandelbrot->width());
-}
-
-QRect MandelbrotTile::destination() const
-{
- int left = m_x*m_mandelbrot->width()/TILING_SIZE;
- int top = m_y*m_mandelbrot->height()/TILING_SIZE;
- int next_left = (m_x+1)*m_mandelbrot->width()/TILING_SIZE;
- int next_top = (m_y+1)*m_mandelbrot->height()/TILING_SIZE;
- return QRect(left, top, next_left-left, next_top-top);
-}
+++ /dev/null
-// Copyright 2008-2009 by Benoît Jacob <jacob.benoit.1@gmail.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License or (at your option) version 3 or any later version
-// accepted by the membership of KDE e.V. (or its successor approved
-// by the membership of KDE e.V.), which shall act as a proxy
-// defined in Section 14 of version 3 of the license.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-#ifndef TILE_HEADER
-#define TILE_HEADER
-
-#include <QPoint>
-#include <QRect>
-#include <QMutex>
-
-#include "global.h"
-
-/** This class represents an abstract tile, that is, just an element of a 8x8 checkerboard.
- * This class is completely unaware of the pixel and complex coordinates of the tile,
- * it only stores a pointer to a Mandelbrot wallpaper
- * and has a method destination() computing the QRect in pixels where the tile belongs.
- */
-class MandelbrotTile
-{
- int m_x, m_y;
- Mandelbrot *m_mandelbrot;
-
- public:
- /** Initializes the tile at given (x,y) location in the checkerboard*/
- void set(Mandelbrot *mandelbrot, int x, int y) { m_mandelbrot = mandelbrot; m_x = x; m_y = y; }
- MandelbrotTile(Mandelbrot *mandelbrot) : m_mandelbrot(mandelbrot) {}
- MandelbrotTile() {} // needed by qRegisterMetaType
- ~MandelbrotTile() {}
- /** \returns the x-coordinate of the tile in the checkerboard */
- int x() const { return m_x; }
- /** \returns the y-coordinate of the tile in the checkerboard */
- int y() const { return m_y; }
- /** \returns the QRect in pixels where the tile belongs in the destination image */
- QRect destination() const;
- /** \returns the complex coordinate of the top-left corner of the tile */
- QPointF affix() const;
-};
-
-Q_DECLARE_METATYPE(MandelbrotTile)
-
-/** This class remembers, in the 8x8 checkerboard, which tiles are already rendered, and uses it in the next()
- * method to determine which tile to render next.
- */
-class MandelbrotTiling
-{
- Mandelbrot *m_mandelbrot;
- int m_number;
- int m_board[TILING_SIZE][TILING_SIZE];
- QPoint m_renderFirst;
- QMutex m_mutex;
-
- public:
- /** Initializes the tile at given (x,y) location in the checkerboard*/
- MandelbrotTiling(Mandelbrot* m) : m_mandelbrot(m) {}
- /** finds the next not-yet-rendered tile to render. \returns true if there
- * is indeed such a next tile to render; false if the rendering is complete. */
- bool next(MandelbrotTile *result);
- /** Resets the checkerboard. \param renderFirst the pixel coordinate of the
- * pixel the user is most interested in. Tiles will be prioritized according to distance
- * from that pixel. */
- void start(const QPointF& renderFirst);
-};
-
-#endif