Warning, file /office/calligra/libs/pigment/KoColorConversionCache.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * Copyright (C) 2007 Cyrille Berger <cberger@cberger.net> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Library General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2 of the License, or (at your option) any later version. 0008 * 0009 * This library is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 * Library General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU Library General Public License 0015 * along with this library; see the file COPYING.LIB. If not, write to 0016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "KoColorConversionCache.h" 0021 0022 #include <QHash> 0023 #include <QList> 0024 #include <QMutex> 0025 #include <QThreadStorage> 0026 0027 #include <KoColorSpace.h> 0028 0029 struct KoColorConversionCacheKey { 0030 0031 KoColorConversionCacheKey(const KoColorSpace* _src, 0032 const KoColorSpace* _dst, 0033 KoColorConversionTransformation::Intent _renderingIntent, 0034 KoColorConversionTransformation::ConversionFlags _conversionFlags) 0035 : src(_src) 0036 , dst(_dst) 0037 , renderingIntent(_renderingIntent) 0038 , conversionFlags(_conversionFlags) 0039 { 0040 } 0041 0042 bool operator==(const KoColorConversionCacheKey& rhs) const { 0043 return (*src == *(rhs.src)) && (*dst == *(rhs.dst)) 0044 && (renderingIntent == rhs.renderingIntent) 0045 && (conversionFlags == rhs.conversionFlags); 0046 } 0047 0048 const KoColorSpace* src; 0049 const KoColorSpace* dst; 0050 KoColorConversionTransformation::Intent renderingIntent; 0051 KoColorConversionTransformation::ConversionFlags conversionFlags; 0052 }; 0053 0054 uint qHash(const KoColorConversionCacheKey& key) 0055 { 0056 return qHash(key.src) + qHash(key.dst) + qHash(key.renderingIntent) + qHash(key.conversionFlags); 0057 } 0058 0059 struct KoColorConversionCache::CachedTransformation { 0060 0061 CachedTransformation(KoColorConversionTransformation* _transfo) 0062 : transfo(_transfo), use(0) 0063 {} 0064 0065 ~CachedTransformation() { 0066 delete transfo; 0067 } 0068 0069 bool available() { 0070 return use == 0; 0071 } 0072 0073 KoColorConversionTransformation* transfo; 0074 int use; 0075 }; 0076 0077 typedef QPair<KoColorConversionCacheKey, KoCachedColorConversionTransformation> FastPathCacheItem; 0078 0079 struct KoColorConversionCache::Private { 0080 QMultiHash< KoColorConversionCacheKey, CachedTransformation*> cache; 0081 QMutex cacheMutex; 0082 0083 QThreadStorage<FastPathCacheItem*> fastStorage; 0084 }; 0085 0086 0087 KoColorConversionCache::KoColorConversionCache() : d(new Private) 0088 { 0089 } 0090 0091 KoColorConversionCache::~KoColorConversionCache() 0092 { 0093 foreach(CachedTransformation* transfo, d->cache) { 0094 delete transfo; 0095 } 0096 delete d; 0097 } 0098 0099 KoCachedColorConversionTransformation KoColorConversionCache::cachedConverter(const KoColorSpace* src, 0100 const KoColorSpace* dst, 0101 KoColorConversionTransformation::Intent _renderingIntent, 0102 KoColorConversionTransformation::ConversionFlags _conversionFlags) 0103 { 0104 KoColorConversionCacheKey key(src, dst, _renderingIntent, _conversionFlags); 0105 0106 FastPathCacheItem *cacheItem = 0107 d->fastStorage.localData(); 0108 0109 if (cacheItem) { 0110 if (cacheItem->first == key) { 0111 return cacheItem->second; 0112 } 0113 } 0114 0115 cacheItem = 0; 0116 0117 QMutexLocker lock(&d->cacheMutex); 0118 QList< CachedTransformation* > cachedTransfos = d->cache.values(key); 0119 if (cachedTransfos.size() != 0) { 0120 foreach(CachedTransformation* ct, cachedTransfos) { 0121 if (ct->available()) { 0122 ct->transfo->setSrcColorSpace(src); 0123 ct->transfo->setDstColorSpace(dst); 0124 0125 cacheItem = new FastPathCacheItem(key, KoCachedColorConversionTransformation(this, ct)); 0126 break; 0127 } 0128 } 0129 } 0130 if (!cacheItem) { 0131 KoColorConversionTransformation* transfo = src->createColorConverter(dst, _renderingIntent, _conversionFlags); 0132 CachedTransformation* ct = new CachedTransformation(transfo); 0133 d->cache.insert(key, ct); 0134 cacheItem = new FastPathCacheItem(key, KoCachedColorConversionTransformation(this, ct)); 0135 } 0136 0137 d->fastStorage.setLocalData(cacheItem); 0138 return cacheItem->second; 0139 } 0140 0141 void KoColorConversionCache::colorSpaceIsDestroyed(const KoColorSpace* cs) 0142 { 0143 d->fastStorage.setLocalData(0); 0144 0145 QMutexLocker lock(&d->cacheMutex); 0146 QMultiHash< KoColorConversionCacheKey, CachedTransformation*>::iterator endIt = d->cache.end(); 0147 for (QMultiHash< KoColorConversionCacheKey, CachedTransformation*>::iterator it = d->cache.begin(); it != endIt;) { 0148 if (it.key().src == cs || it.key().dst == cs) { 0149 Q_ASSERT(it.value()->available()); // That's terribely evil, if that assert fails, that means that someone is using a color transformation with a color space which is currently being deleted 0150 delete it.value(); 0151 it = d->cache.erase(it); 0152 } else { 0153 ++it; 0154 } 0155 } 0156 } 0157 0158 //--------- KoCachedColorConversionTransformation ----------// 0159 0160 struct KoCachedColorConversionTransformation::Private { 0161 KoColorConversionCache* cache; 0162 KoColorConversionCache::CachedTransformation* transfo; 0163 }; 0164 0165 0166 KoCachedColorConversionTransformation::KoCachedColorConversionTransformation(KoColorConversionCache* cache, KoColorConversionCache::CachedTransformation* transfo) : d(new Private) 0167 { 0168 Q_ASSERT(transfo->available()); 0169 d->cache = cache; 0170 d->transfo = transfo; 0171 d->transfo->use++; 0172 } 0173 0174 KoCachedColorConversionTransformation::KoCachedColorConversionTransformation(const KoCachedColorConversionTransformation& rhs) : d(new Private(*rhs.d)) 0175 { 0176 d->transfo->use++; 0177 } 0178 0179 KoCachedColorConversionTransformation::~KoCachedColorConversionTransformation() 0180 { 0181 d->transfo->use--; 0182 Q_ASSERT(d->transfo->use >= 0); 0183 delete d; 0184 } 0185 0186 const KoColorConversionTransformation* KoCachedColorConversionTransformation::transformation() const 0187 { 0188 return d->transfo->transfo; 0189 } 0190