diff --git a/interfaces/KoGenericRegistry.h b/interfaces/KoGenericRegistry.h index b6ea309fee..25f55dd29f 100644 --- a/interfaces/KoGenericRegistry.h +++ b/interfaces/KoGenericRegistry.h @@ -1,170 +1,201 @@ /* This file is part of the KDE project * Copyright (c) 2004 Cyrille Berger * Copyright (c) 2006 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef _KO_GENERIC_REGISTRY_H_ #define _KO_GENERIC_REGISTRY_H_ #include #include #include +#include "kis_assert.h" + /** * Base class for registry objects. * * Registered objects are owned by the registry. * * Items are mapped by QString as a unique Id. * * Example of use: * @code * class KoMyClassRegistry : public KoGenericRegistry { * public: * static KoMyClassRegistry * instance(); * private: * static KoMyClassRegistry* s_instance; * }; * * KoMyClassRegistry *KoMyClassRegistry::s_instance = 0; * KoMyClassRegistry * KoMyClassRegistry::instance() * { * if(s_instance == 0) * { * s_instance = new KoMyClassRegistry; * } * return s_instance; * } * * @endcode */ template class KoGenericRegistry { public: KoGenericRegistry() { } virtual ~KoGenericRegistry() { m_hash.clear(); } public: /** * Add an object to the registry. If it is a QObject, make sure it isn't in the * QObject ownership hierarchy, since the registry itself is responsbile for * deleting it. * * @param item the item to add (NOTE: T must have an QString id() const function) */ void add(T item) { - Q_ASSERT(item); - QString id = item->id(); + KIS_SAFE_ASSERT_RECOVER_RETURN(item); + + const QString id = item->id(); + KIS_SAFE_ASSERT_RECOVER_NOOP(!m_aliases.contains(id)); + if (m_hash.contains(id)) { m_doubleEntries << value(id); remove(id); } m_hash.insert(id, item); } /** * add an object to the registry * @param id the id of the object * @param item the item to add */ void add(const QString &id, T item) { - Q_ASSERT(item); + KIS_SAFE_ASSERT_RECOVER_RETURN(item); + KIS_SAFE_ASSERT_RECOVER_NOOP(!m_aliases.contains(id)); + if (m_hash.contains(id)) { m_doubleEntries << value(id); remove(id); } m_hash.insert(id, item); } /** * This function removes an item from the registry */ void remove(const QString &id) { m_hash.remove(id); } + void addAlias(const QString &alias, const QString &id) + { + KIS_SAFE_ASSERT_RECOVER_NOOP(!m_hash.contains(alias)); + m_aliases[alias] = id; + } + + void removeAlias(const QString &alias) + { + m_aliases.remove(alias); + } + /** * Retrieve the object from the registry based on the unique * identifier string. * * @param id the id */ T get(const QString &id) const { return value(id); } /** * @return if there is an object stored in the registry identified * by the id. * @param id the unique identifier string */ bool contains(const QString &id) const { - return m_hash.contains(id); + bool result = m_hash.contains(id); + + if (!result && m_aliases.contains(id)) { + result = m_hash.contains(m_aliases.value(id)); + } + + return result; } /** * Retrieve the object from the registry based on the unique identifier string * @param id the id */ const T value(const QString &id) const { - return m_hash.value(id); + T result = m_hash.value(id); + + if (!result && m_aliases.contains(id)) { + result = m_hash.value(m_aliases.value(id)); + } + + return result; } /** * @return a list of all keys */ QList keys() const { return m_hash.keys(); } int count() const { return m_hash.count(); } QList values() const { return m_hash.values(); } QList doubleEntries() const { return m_doubleEntries; } private: QList m_doubleEntries; private: QHash m_hash; + QHash m_aliases; }; #endif diff --git a/libs/image/kis_filter_strategy.cc b/libs/image/kis_filter_strategy.cc index 802ec01736..73fc75609e 100644 --- a/libs/image/kis_filter_strategy.cc +++ b/libs/image/kis_filter_strategy.cc @@ -1,238 +1,239 @@ /* * Copyright (c) 2004 Michael Thaler * Copyright (c) 2005 C. Boemann * Copyright (c) 2013 Juan Palacios * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_filter_strategy.h" #include #include #include #include "kis_debug.h" Q_GLOBAL_STATIC(KisFilterStrategyRegistry, s_instance) qreal KisHermiteFilterStrategy::valueAt(qreal t) const { /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */ if (t < 0.0) t = -t; if (t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0); return(0.0); } qint32 KisHermiteFilterStrategy::intValueAt(qint32 t) const { /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */ if (t < 0) t = -t; if (t < 256) { t = (2 * t - 3 * 256) * t * t + (256 << 16); //go from .24 fixed point to .8 fixedpoint (hack only works with positive numbers, which it is) t = (t + 0x8000) >> 16; // go from .8 fixed point to 8bitscale. ie t = (t*255)/256; if (t >= 128) return t - 1; return t; } return(0); } qint32 KisBicubicFilterStrategy::intValueAt(qint32 t) const { /* f(t) = 1.5|t|^3 - 2.5|t|^2 + 1, -1 <= t <= 1 */ if (t < 0) t = -t; if (t < 256) { t = (3 * t - 5 * 256) * t * t / 2 + (256 << 16); //go from .24 fixed point to .8 fixedpoint (hack only works with positive numbers, which it is) t = (t + 0x8000) >> 16; // go from .8 fixed point to 8bitscale. ie t = (t*255)/256; if (t >= 128) return t - 1; return t; } if (t < 512) { /* f(t) = -0.5|t|^3 + 2.5|t|^2 + 4|t| - 2, -2 <= t <= 2 */ t = ((-t + 5 * 256) * t / 2 - 4 * 256 * 256) * t + (2 * 256 << 16); //go from .24 fixed point to .8 fixedpoint (hack only works with positive numbers, which it is) t = (t + 0x8000) >> 16; // go from .8 fixed point to 8bitscale. ie t = (t*255)/256; if (t >= 128) return t - 1; return t; } return(0); } qreal KisBoxFilterStrategy::valueAt(qreal t) const { if ((t > -0.5) && (t <= 0.5)) return(1.0); return(0.0); } qint32 KisBoxFilterStrategy::intValueAt(qint32 t) const { /* f(t) = 1, -0.5 < t <= 0.5 */ if ((t > -128) && (t <= 128)) return 255; return 0; } qreal KisBilinearFilterStrategy::valueAt(qreal t) const { if (t < 0.0) t = -t; if (t < 1.0) return(1.0 - t); return(0.0); } qint32 KisBilinearFilterStrategy::intValueAt(qint32 t) const { /* f(t) = |t|, -1 <= t <= 1 */ if (t < 0) t = -t; if (t < 256) { // calc 256-1 but also go from .8 fixed point to 8bitscale. ie t = (t*255)/256; ie: if(t>=128) return t-1; if (t >= 128) return 256 - t; return 255 - t; } return(0); } qreal KisBellFilterStrategy::valueAt(qreal t) const { if (t < 0) t = -t; if (t < .5) return(.75 - (t * t)); if (t < 1.5) { t = (t - 1.5); return(.5 *(t * t)); } return(0.0); } qreal KisBSplineFilterStrategy::valueAt(qreal t) const { qreal tt; if (t < 0) t = -t; if (t < 1) { tt = t * t; return((.5 * tt * t) - tt + (2.0 / 3.0)); } else if (t < 2) { t = 2 - t; return((1.0 / 6.0) *(t * t * t)); } return(0.0); } qreal KisLanczos3FilterStrategy::valueAt(qreal t) const { if (t < 0) t = -t; if (t < 3.0) return(sinc(t) * sinc(t / 3.0)); return(0.0); } qreal KisLanczos3FilterStrategy::sinc(qreal x) const { const qreal pi = 3.1415926535897932385; x *= pi; if (x != 0) return(sin(x) / x); return(1.0); } qreal KisMitchellFilterStrategy::valueAt(qreal t) const { const qreal B = 1.0 / 3.0; const qreal C = 1.0 / 3.0; qreal tt; tt = t * t; if (t < 0) t = -t; if (t < 1.0) { t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt)) + ((-18.0 + 12.0 * B + 6.0 * C) * tt) + (6.0 - 2 * B)); return(t / 6.0); } else if (t < 2.0) { t = (((-1.0 * B - 6.0 * C) * (t * tt)) + ((6.0 * B + 30.0 * C) * tt) + ((-12.0 * B - 48.0 * C) * t) + (8.0 * B + 24 * C)); return(t / 6.0); } return(0.0); } KisFilterStrategyRegistry::KisFilterStrategyRegistry() { } KisFilterStrategyRegistry::~KisFilterStrategyRegistry() { Q_FOREACH (const QString &id, keys()) { delete get(id); } dbgRegistry << "deleting KisFilterStrategyRegistry"; } KisFilterStrategyRegistry* KisFilterStrategyRegistry::instance() { if (!s_instance.exists()) { + s_instance->add(new KisBoxFilterStrategy); + s_instance->addAlias("Box", "NearestNeighbor"); + s_instance->add(new KisHermiteFilterStrategy); s_instance->add(new KisBicubicFilterStrategy); - s_instance->add(new KisBoxFilterStrategy); s_instance->add(new KisBilinearFilterStrategy); s_instance->add(new KisBellFilterStrategy); s_instance->add(new KisBSplineFilterStrategy); s_instance->add(new KisLanczos3FilterStrategy); s_instance->add(new KisMitchellFilterStrategy); - } return s_instance; } QList KisFilterStrategyRegistry::listKeys() const { QList answer; Q_FOREACH (const QString key, keys()) { answer.append(KoID(key, get(key)->name())); } return answer; } QString KisFilterStrategyRegistry::formattedDescriptions() const { QString formatedDescription(""); Q_FOREACH (const QString key, keys()) { KisFilterStrategy *strategy = get(key); QString description = strategy->description(); if (!description.isEmpty()) { formatedDescription.append("

"); formatedDescription.append(strategy->name()); formatedDescription.append(": "); formatedDescription.append(description); formatedDescription.append("

"); } } formatedDescription.append(""); return formatedDescription; }