Krita Source Code Documentation
Loading...
Searching...
No Matches
KoColorProfileStorage Class Reference

The KoColorProfileStorage class is a "composite subclass" of KoColorSpaceRegistry that ensures that the access to profiles is guarded by a separate lock and the hierarchy of locks is always followed (which avoid deadlocks). More...

#include <KoColorProfileStorage.h>

Classes

struct  Private
 

Public Member Functions

void addProfile (KoColorProfile *profile)
 
void addProfileAlias (const QString &name, const QString &to)
 
bool containsProfile (const KoColorProfile *profile)
 containsProfile shows if a profile is registered in the storage
 
 KoColorProfileStorage ()
 
QString profileAlias (const QString &name) const
 
const KoColorProfileprofileByName (const QString &name) const
 
const KoColorProfileprofileByUniqueId (const QByteArray &id) const
 
QList< const KoColorProfile * > profilesFor (const KoColorProfileQuery &query, double error=0.0001)
 profilesFor Return the list of profiles for a colorspace represented by it's colorants and type.
 
QList< const KoColorProfile * > profilesFor (const KoColorSpaceFactory *csf) const
 
void removeProfile (KoColorProfile *profile)
 
void removeProfileAlias (const QString &name)
 
 ~KoColorProfileStorage ()
 

Private Attributes

const QScopedPointer< Privated
 

Detailed Description

The KoColorProfileStorage class is a "composite subclass" of KoColorSpaceRegistry that ensures that the access to profiles is guarded by a separate lock and the hierarchy of locks is always followed (which avoid deadlocks).

Registry locking hierarchy is basically the following:

1) KoColorSpaceRegistry::Private::registrylock 2) KoColorProfileStorage::Private::lock

It means that we can take any single lock if we need it separately, but if we need to take both of them, we should always take them is a specified order.

Encapsulation of the profile accesses inside a separate class lets us follow this rule without even thinking of it. KoColorProfileStorage just never calls any method of the registry, therefore lock order inversion is not possible,

Definition at line 39 of file KoColorProfileStorage.h.

Constructor & Destructor Documentation

◆ KoColorProfileStorage()

KoColorProfileStorage::KoColorProfileStorage ( )

Definition at line 51 of file KoColorProfileStorage.cpp.

52 : d(new Private)
53{
54
55}
const QScopedPointer< Private > d

◆ ~KoColorProfileStorage()

KoColorProfileStorage::~KoColorProfileStorage ( )

Definition at line 57 of file KoColorProfileStorage.cpp.

58{
59}

Member Function Documentation

◆ addProfile()

void KoColorProfileStorage::addProfile ( KoColorProfile * profile)

Register the profile in the storage

Parameters
profilethe new profile to be registered

Definition at line 61 of file KoColorProfileStorage.cpp.

62{
63 QWriteLocker locker(&d->lock);
64
65 if (profile->valid()) {
66 d->profileMap[profile->name()] = profile;
67 if (d->profileUniqueIdMap.contains(profile->uniqueId())) {
68 //warnPigment << "Duplicated profile" << profile->name() << profile->fileName() << d->profileUniqueIdMap[profile->uniqueId()]->fileName();
69 d->duplicates.append(d->profileUniqueIdMap[profile->uniqueId()]);
70 }
71 d->profileUniqueIdMap.insert(profile->uniqueId(), profile);
72 }
73}
virtual QByteArray uniqueId() const =0
virtual bool valid() const =0

References d, KoColorProfile::name, KoColorProfile::uniqueId(), and KoColorProfile::valid().

◆ addProfileAlias()

void KoColorProfileStorage::addProfileAlias ( const QString & name,
const QString & to )

Create an alias to a profile with a different name. Then profileByName will return the profile to when passed name as a parameter.

Aliases are considered 'weak'. If a real profile with the name name is present (or added), it shadows the existing alias. If such an explicit profile gets removed, then the alias takes its place again.

Definition at line 90 of file KoColorProfileStorage.cpp.

91{
92 QWriteLocker l(&d->lock);
93 d->profileAlias[name] = to;
94}
const char * name(StandardAction id)

References d.

◆ containsProfile()

bool KoColorProfileStorage::containsProfile ( const KoColorProfile * profile)

containsProfile shows if a profile is registered in the storage

Definition at line 84 of file KoColorProfileStorage.cpp.

85{
86 QReadLocker l(&d->lock);
87 return d->profileMap.contains(profile->name());
88}

References d, and KoColorProfile::name.

◆ profileAlias()

QString KoColorProfileStorage::profileAlias ( const QString & name) const
Returns
the profile alias, or name if not aliased

Profile aliases are considered 'weak', i.e. they can be overridden by a read profile added to the storage.

Definition at line 102 of file KoColorProfileStorage.cpp.

103{
104 QReadLocker l(&d->lock);
109 return d->profileMap.contains(name) ? name : d->profileAlias.value(name, name);
110}

References d.

◆ profileByName()

const KoColorProfile * KoColorProfileStorage::profileByName ( const QString & name) const

Return a profile by its given name, or 0 if none registered.

Returns
a profile by its given name, or 0 if none registered.
Parameters
namethe product name as set on the profile.
See also
addProfile()
KoColorProfile::productName()

Profile aliases are considered 'weak', i.e. they can be overridden by a read profile added to the storage.

Definition at line 112 of file KoColorProfileStorage.cpp.

113{
114 QReadLocker l(&d->lock);
119 if (d->profileMap.contains(name)) {
120 return d->profileMap[name];
121 }
122
123 return d->profileMap.value(d->profileAlias.value(name, name), 0);
124}

References d.

◆ profileByUniqueId()

const KoColorProfile * KoColorProfileStorage::profileByUniqueId ( const QByteArray & id) const

Returns a profile by its unique id stored/calculated in the header. The first call to this function might take long, because the map is created on the first use only (atm used by SVG only)

Parameters
idunique ProfileID of the profile (MD5 sum of its header)
Returns
the profile or 0 if not found

Definition at line 145 of file KoColorProfileStorage.cpp.

146{
147 QReadLocker l(&d->lock);
148 if (d->profileUniqueIdMap.isEmpty()) {
149 l.unlock();
150 d->populateUniqueIdMap();
151 l.relock();
152 }
153 return d->profileUniqueIdMap.value(id, 0);
154
155}

References d.

◆ profilesFor() [1/2]

QList< const KoColorProfile * > KoColorProfileStorage::profilesFor ( const KoColorProfileQuery & query,
double error = 0.0001 )

profilesFor Return the list of profiles for a colorspace represented by it's colorants and type.

Parameters
colorantslist of at the least 2 values representing the whitePoint xyY, or 8 representing whitePoint, red, green and blue x and y xyY values. If the colorant type is set, the colorants will not be used.
colorantTypethe named colorantType, if 2, it's undefined and the colorants will be used.
transferTypethe name transfer type, if 2 it's undefined.
errorthe margin of error with which the colorants get compared.
Returns
list of available profiles.

Definition at line 176 of file KoColorProfileStorage.cpp.

177{
179
180 if (!query.isValid()) {
181 return profiles;
182 }
183
184 QReadLocker l(&d->lock);
185 for (const KoColorProfile* profile : d->profileMap) {
186 bool colorantMatch = (!query.rgbColorants.isEmpty() || query.primaries != PRIMARIES_UNSPECIFIED);
187 bool colorantTypeMatch = (query.primaries == PRIMARIES_UNSPECIFIED);
188 bool transferMatch = (query.transfer == TRC_UNSPECIFIED);
189 if (query.primaries != PRIMARIES_UNSPECIFIED) {
190 if (int(profile->getColorPrimaries()) == query.primaries) {
191 colorantTypeMatch = true;
192 }
193 }
194 if (query.transfer != TRC_UNSPECIFIED) {
195 if (int(profile->getTransferCharacteristics()) == query.transfer) {
196 transferMatch = true;
197 }
198 }
199
200 if (!query.rgbColorants.isEmpty() && query.primaries == PRIMARIES_UNSPECIFIED) {
201 KoColorimetryUtils::xyY wp = profile->getWhitePointxyY();
202 if (profile->getColorantsxyY().size() == query.rgbColorants.size()) {
203 QVector<KoColorimetryUtils::xyY> col = profile->getColorantsxyY();
204 if (col.isEmpty()) {
205 // too few colorants, skip.
206 continue;
207 }
208
209 colorantMatch = (std::fabs(wp.x - query.whitePoint.x) < error) && (std::fabs(wp.y - query.whitePoint.y) < error);
210 if (!colorantMatch) {
211 continue;
212 }
213
214 for (int i = 0; i < col.size(); i++) {
215 colorantMatch = (std::fabs(col[i].x - query.rgbColorants[i].x) < error) && (std::fabs(col[i].y - query.rgbColorants[i].y) < error);
216 if (!colorantMatch) {
217 break;
218 }
219 }
220 } else {
221 if (std::fabs(wp.x - query.whitePoint.x) < error && std::fabs(wp.y - query.whitePoint.y) < error) {
222 colorantMatch = true;
223 }
224 }
225 }
226
227 if (transferMatch && colorantMatch && colorantTypeMatch) {
228 profiles.push_back(profile);
229 }
230 }
231
232 return profiles;
233}
@ PRIMARIES_UNSPECIFIED
TransferCharacteristics transfer
CICP-compatible enum value representing the white point and primaries.
ColorPrimaries primaries
Rgb Primaries of the profile. When empty, this is a query for a greyscale profile.
bool isValid() const
CICP-compatible enum value representing the transfer function.
QList< KoColorimetryUtils::xy > rgbColorants
The desired white point of the profile.
KoColorimetryUtils::xy whitePoint

References d, KoColorProfileQuery::isValid(), KoColorProfileQuery::primaries, PRIMARIES_UNSPECIFIED, KoColorProfileQuery::rgbColorants, KoColorProfileQuery::transfer, TRC_UNSPECIFIED, KoColorProfileQuery::whitePoint, KoColorimetryUtils::xy::x, KoColorimetryUtils::xyY::x, KoColorimetryUtils::xy::y, and KoColorimetryUtils::xyY::y.

◆ profilesFor() [2/2]

QList< const KoColorProfile * > KoColorProfileStorage::profilesFor ( const KoColorSpaceFactory * csf) const

Return the list of profiles for a colorspace represented by its factory. Profiles will not work with any color space, you can query which profiles that are registered with this registry can be used in combination with the argument factory.

Parameters
csfis a factory for the requested color space
Returns
a list of profiles for the factory

Definition at line 157 of file KoColorProfileStorage.cpp.

158{
160 if (!csf) return profiles;
161
162 QReadLocker l(&d->lock);
163
164 QHash<QString, KoColorProfile * >::ConstIterator it;
165 for (it = d->profileMap.constBegin(); it != d->profileMap.constEnd(); ++it) {
166 KoColorProfile * profile = it.value();
167 if (csf->profileIsCompatible(profile)) {
168 Q_ASSERT(profile);
169 // if (profile->colorSpaceSignature() == csf->colorSpaceSignature()) {
170 profiles.push_back(profile);
171 }
172 }
173 return profiles;
174}
virtual bool profileIsCompatible(const KoColorProfile *profile) const =0

References d, and KoColorSpaceFactory::profileIsCompatible().

◆ removeProfile()

void KoColorProfileStorage::removeProfile ( KoColorProfile * profile)

Removes the profile from the storage. Please note that the caller should delete the profile object himself!

Parameters
profilethe profile to be removed

Definition at line 75 of file KoColorProfileStorage.cpp.

76{
77 QWriteLocker locker(&d->lock);
78
79 d->profileMap.remove(profile->name());
80 d->profileUniqueIdMap.remove(profile->uniqueId());
81 d->duplicates.removeAll(profile);
82}

References d, KoColorProfile::name, and KoColorProfile::uniqueId().

◆ removeProfileAlias()

void KoColorProfileStorage::removeProfileAlias ( const QString & name)

Remove a profile name if exists

Definition at line 96 of file KoColorProfileStorage.cpp.

97{
98 QWriteLocker l(&d->lock);
99 d->profileAlias.remove(name);
100}

References d.

Member Data Documentation

◆ d

const QScopedPointer<Private> KoColorProfileStorage::d
private

Definition at line 128 of file KoColorProfileStorage.h.


The documentation for this class was generated from the following files: