Krita Source Code Documentation
Loading...
Searching...
No Matches
KisUniqueColorSet.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2021 Mathias Wein <lynx.mw+kde@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
7#include "KisUniqueColorSet.h"
8
9#include <QHash>
10#include <deque>
11#include <algorithm>
12
13uint qHash(const KoColor &color, uint seed = 0)
14{
15 // hash the color data bytes, while using the hash of the colorspace pointer as seed
16 // TODO: take pixelSize directly from the color.m_size (private member)
17 return qHashBits(color.data(), color.colorSpace()->pixelSize(), qHash(color.colorSpace(), seed));
18}
19
21{
23 {
24 // larger key == more recent == earlier in list
25 return (lhs->key > rhs->key);
26 }
27
29 quint64 key;
30};
31
33{
34 QHash<KoColor, KisUniqueColorSet::ColorEntry*> colorHash;
35 std::deque<ColorEntry*> history;
36 size_t maxSize {200};
37 quint64 key {0};
38};
39
41 : QObject(parent)
42 , d(new Private)
43{ }
44
46{
47 for (ColorEntry *entry: d->history) {
48 delete entry;
49 }
50}
51
53{
54 auto hashEntry = d->colorHash.find(color);
55 if (hashEntry != d->colorHash.end()) {
56 auto historyEl = std::lower_bound(d->history.begin(), d->history.end(), *hashEntry, &ColorEntry::less);
57 if (historyEl != d->history.end()) {
58 int oldPos = historyEl - d->history.begin();
59 if (historyEl == d->history.begin()) {
60 KIS_ASSERT((*historyEl)->key == d->key);
61 return;
62 }
63 ColorEntry *node = *historyEl;
64 d->history.erase(historyEl);
65 node->key = ++d->key;
66 d->history.push_front(node);
67 Q_EMIT sigColorMoved(oldPos, 0);
68 }
69 else {
70 qDebug() << "inconsistent color history state!";
71 }
72 }
73 else {
74 ColorEntry *entry;
75 if (d->history.size() >= d->maxSize) {
76 entry = d->history.back();
77 d->history.pop_back();
78 KIS_ASSERT(d->colorHash.remove(entry->color) == 1);
79 entry->color = color;
80 entry->key = ++d->key;
81 Q_EMIT sigColorRemoved(d->maxSize - 1);
82 }
83 else {
84 entry = new ColorEntry {color, ++d->key};
85 }
86 d->colorHash.insert(color, entry);
87 d->history.push_front(entry);
88 Q_EMIT sigColorAdded(0);
89 }
90}
91
93{
94 if (index < 0 || index >= static_cast<int>(d->history.size())) {
95 return KoColor();
96 }
97 return d->history.at(index)->color;
98}
99
101{
102 return static_cast<int>(d->history.size());
103}
104
106{
107 for (ColorEntry *entry: d->history) {
108 delete entry;
109 }
110 d->history.clear();
111 d->colorHash.clear();
112 d->key = 0;
113 Q_EMIT sigReset();
114}
uint qHash(const KoColor &color, uint seed=0)
unsigned int uint
void sigColorRemoved(int position)
void sigColorAdded(int position)
QScopedPointer< Private > d
void addColor(const KoColor &color)
KoColor color(int index) const
void sigColorMoved(int from, int to)
KisUniqueColorSet(QObject *parent=nullptr)
virtual quint32 pixelSize() const =0
quint8 * data()
Definition KoColor.h:144
const KoColorSpace * colorSpace() const
return the current colorSpace
Definition KoColor.h:82
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
static bool less(const KisUniqueColorSet::ColorEntry *lhs, const KisUniqueColorSet::ColorEntry *rhs)
QHash< KoColor, KisUniqueColorSet::ColorEntry * > colorHash
std::deque< ColorEntry * > history