annotate layer/ColourDatabase.cpp @ 1534:bfd8b22fd67c

Fix #1904 Scrolling colour 3d plot does not always work when in View normalisation mode. We shouldn't imagine we've just invalidated the cache if the truth is that we've only just created the renderer
author Chris Cannam
date Wed, 09 Oct 2019 13:45:17 +0100
parents ad86aa712d11
children 57a4ee52ad69
rev   line source
Chris@376 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@376 2
Chris@376 3 /*
Chris@376 4 Sonic Visualiser
Chris@376 5 An audio file viewer and annotation editor.
Chris@376 6 Centre for Digital Music, Queen Mary, University of London.
Chris@376 7 This file copyright 2007 QMUL.
Chris@376 8
Chris@376 9 This program is free software; you can redistribute it and/or
Chris@376 10 modify it under the terms of the GNU General Public License as
Chris@376 11 published by the Free Software Foundation; either version 2 of the
Chris@376 12 License, or (at your option) any later version. See the file
Chris@376 13 COPYING included with this distribution for more information.
Chris@376 14 */
Chris@376 15
Chris@376 16 #include "ColourDatabase.h"
Chris@376 17 #include "base/XmlExportable.h"
Chris@376 18
Chris@376 19 #include <QPainter>
Chris@376 20
Chris@1445 21 //#define DEBUG_COLOUR_DATABASE 1
Chris@1445 22
Chris@376 23 ColourDatabase
Chris@376 24 ColourDatabase::m_instance;
Chris@376 25
Chris@376 26 ColourDatabase *
Chris@376 27 ColourDatabase::getInstance()
Chris@376 28 {
Chris@376 29 return &m_instance;
Chris@376 30 }
Chris@376 31
Chris@376 32 ColourDatabase::ColourDatabase()
Chris@376 33 {
Chris@376 34 }
Chris@376 35
Chris@376 36 int
Chris@376 37 ColourDatabase::getColourCount() const
Chris@376 38 {
Chris@904 39 return int(m_colours.size());
Chris@376 40 }
Chris@376 41
Chris@376 42 QString
Chris@376 43 ColourDatabase::getColourName(int c) const
Chris@376 44 {
Chris@904 45 if (!in_range_for(m_colours, c)) return "";
Chris@376 46 return m_colours[c].name;
Chris@376 47 }
Chris@376 48
Chris@376 49 QColor
Chris@376 50 ColourDatabase::getColour(int c) const
Chris@376 51 {
Chris@904 52 if (!in_range_for(m_colours, c)) return Qt::black;
Chris@376 53 return m_colours[c].colour;
Chris@376 54 }
Chris@376 55
Chris@376 56 QColor
Chris@376 57 ColourDatabase::getColour(QString name) const
Chris@376 58 {
Chris@904 59 for (auto &c: m_colours) {
Chris@904 60 if (c.name == name) return c.colour;
Chris@376 61 }
Chris@376 62
Chris@376 63 return Qt::black;
Chris@376 64 }
Chris@376 65
Chris@376 66 int
Chris@376 67 ColourDatabase::getColourIndex(QString name) const
Chris@376 68 {
Chris@376 69 int index = 0;
Chris@904 70 for (auto &c: m_colours) {
Chris@904 71 if (c.name == name) return index;
Chris@376 72 ++index;
Chris@376 73 }
Chris@376 74
Chris@376 75 return -1;
Chris@376 76 }
Chris@376 77
Chris@376 78 int
Chris@904 79 ColourDatabase::getColourIndex(QColor col) const
Chris@376 80 {
Chris@376 81 int index = 0;
Chris@904 82 for (auto &c: m_colours) {
Chris@904 83 if (c.colour == col) return index;
Chris@376 84 ++index;
Chris@376 85 }
Chris@376 86
Chris@376 87 return -1;
Chris@376 88 }
Chris@376 89
Chris@1445 90 int
Chris@1445 91 ColourDatabase::getNearbyColourIndex(QColor col) const
Chris@1445 92 {
Chris@1445 93 int index = 0;
Chris@1445 94 int closestIndex = -1;
Chris@1445 95 int closestDistance = 0;
Chris@1445 96
Chris@1445 97 for (auto &c: m_colours) {
Chris@1445 98 int distance =
Chris@1445 99 std::abs(col.red() - c.colour.red()) +
Chris@1445 100 std::abs(col.green() - c.colour.green()) +
Chris@1445 101 std::abs(col.blue() - c.colour.blue());
Chris@1445 102 #ifdef DEBUG_COLOUR_DATABASE
Chris@1445 103 SVDEBUG << "getNearbyColourIndex: comparing " << c.colour.name()
Chris@1445 104 << " to " << col.name() << ": distance = " << distance << endl;
Chris@1445 105 #endif
Chris@1445 106 if (closestIndex < 0 || distance < closestDistance) {
Chris@1445 107 closestIndex = index;
Chris@1445 108 closestDistance = distance;
Chris@1445 109 #ifdef DEBUG_COLOUR_DATABASE
Chris@1445 110 SVDEBUG << "(this is the best so far)" << endl;
Chris@1445 111 #endif
Chris@1445 112 }
Chris@1445 113 ++index;
Chris@1445 114 }
Chris@1445 115
Chris@1445 116 #ifdef DEBUG_COLOUR_DATABASE
Chris@1445 117 SVDEBUG << "returning " << closestIndex << endl;
Chris@1445 118 #endif
Chris@1445 119 return closestIndex;
Chris@1445 120 }
Chris@1445 121
Chris@1367 122 QColor
Chris@1367 123 ColourDatabase::getContrastingColour(int c) const
Chris@1367 124 {
Chris@1367 125 QColor col = getColour(c);
Chris@1445 126 QColor contrasting = Qt::red;
Chris@1445 127 bool dark = (col.red() < 240 && col.green() < 240 && col.blue() < 240);
Chris@1445 128 if (dark) {
Chris@1445 129 if (col.red() > col.blue()) {
Chris@1445 130 if (col.green() > col.blue()) {
Chris@1445 131 contrasting = Qt::blue;
Chris@1445 132 } else {
Chris@1445 133 contrasting = Qt::yellow;
Chris@1445 134 }
Chris@1367 135 } else {
Chris@1445 136 if (col.green() > col.blue()) {
Chris@1445 137 contrasting = Qt::yellow;
Chris@1445 138 } else {
Chris@1445 139 contrasting = Qt::red;
Chris@1445 140 }
Chris@1367 141 }
Chris@1367 142 } else {
Chris@1445 143 if (col.red() > 230 && col.green() > 230 && col.blue() > 230) {
Chris@1445 144 contrasting = QColor(30, 150, 255);
Chris@1367 145 } else {
Chris@1445 146 contrasting = QColor(255, 188, 80);
Chris@1367 147 }
Chris@1367 148 }
Chris@1445 149 #ifdef DEBUG_COLOUR_DATABASE
Chris@1445 150 SVDEBUG << "getContrastingColour(" << col.name() << "): dark = " << dark
Chris@1445 151 << ", returning " << contrasting.name() << endl;
Chris@1445 152 #endif
Chris@1445 153 return contrasting;
Chris@1367 154 }
Chris@1367 155
Chris@376 156 bool
Chris@376 157 ColourDatabase::useDarkBackground(int c) const
Chris@376 158 {
Chris@904 159 if (!in_range_for(m_colours, c)) return false;
Chris@376 160 return m_colours[c].darkbg;
Chris@376 161 }
Chris@376 162
Chris@376 163 void
Chris@376 164 ColourDatabase::setUseDarkBackground(int c, bool dark)
Chris@376 165 {
Chris@904 166 if (!in_range_for(m_colours, c)) return;
Chris@376 167 if (m_colours[c].darkbg != dark) {
Chris@376 168 m_colours[c].darkbg = dark;
Chris@376 169 emit colourDatabaseChanged();
Chris@376 170 }
Chris@376 171 }
Chris@376 172
Chris@376 173 int
Chris@376 174 ColourDatabase::addColour(QColor c, QString name)
Chris@376 175 {
Chris@376 176 int index = 0;
Chris@904 177
Chris@376 178 for (ColourList::iterator i = m_colours.begin();
Chris@376 179 i != m_colours.end(); ++i) {
Chris@376 180 if (i->name == name) {
Chris@376 181 i->colour = c;
Chris@376 182 return index;
Chris@376 183 }
Chris@376 184 ++index;
Chris@376 185 }
Chris@376 186
Chris@376 187 ColourRec rec;
Chris@376 188 rec.colour = c;
Chris@376 189 rec.name = name;
Chris@376 190 rec.darkbg = false;
Chris@376 191 m_colours.push_back(rec);
Chris@376 192 emit colourDatabaseChanged();
Chris@376 193 return index;
Chris@376 194 }
Chris@376 195
Chris@376 196 void
Chris@376 197 ColourDatabase::removeColour(QString name)
Chris@376 198 {
Chris@376 199 for (ColourList::iterator i = m_colours.begin();
Chris@376 200 i != m_colours.end(); ++i) {
Chris@376 201 if (i->name == name) {
Chris@376 202 m_colours.erase(i);
Chris@376 203 return;
Chris@376 204 }
Chris@376 205 }
Chris@376 206 }
Chris@376 207
Chris@376 208 void
Chris@376 209 ColourDatabase::getStringValues(int index,
Chris@376 210 QString &colourName,
Chris@376 211 QString &colourSpec,
Chris@376 212 QString &darkbg) const
Chris@376 213 {
Chris@376 214 colourName = "";
Chris@376 215 colourSpec = "";
Chris@904 216 if (!in_range_for(m_colours, index)) return;
Chris@376 217
Chris@376 218 colourName = getColourName(index);
Chris@376 219 QColor c = getColour(index);
Chris@376 220 colourSpec = XmlExportable::encodeColour(c.red(), c.green(), c.blue());
Chris@376 221 darkbg = useDarkBackground(index) ? "true" : "false";
Chris@376 222 }
Chris@376 223
Chris@376 224 int
Chris@376 225 ColourDatabase::putStringValues(QString colourName,
Chris@376 226 QString colourSpec,
Chris@376 227 QString darkbg)
Chris@376 228 {
Chris@376 229 int index = -1;
Chris@376 230 if (colourSpec != "") {
Chris@1266 231 QColor colour(colourSpec);
Chris@376 232 index = getColourIndex(colour);
Chris@376 233 if (index < 0) {
Chris@376 234 index = addColour(colour,
Chris@376 235 colourName == "" ? colourSpec : colourName);
Chris@376 236 }
Chris@376 237 } else if (colourName != "") {
Chris@376 238 index = getColourIndex(colourName);
Chris@376 239 }
Chris@376 240 if (index >= 0) {
Chris@376 241 setUseDarkBackground(index, darkbg == "true");
Chris@376 242 }
Chris@376 243 return index;
Chris@376 244 }
Chris@376 245
Chris@376 246 void
Chris@376 247 ColourDatabase::getColourPropertyRange(int *min, int *max) const
Chris@376 248 {
Chris@376 249 ColourDatabase *db = getInstance();
Chris@376 250 if (min) *min = 0;
Chris@376 251 if (max) {
Chris@376 252 *max = 0;
Chris@376 253 if (db->getColourCount() > 0) *max = db->getColourCount()-1;
Chris@376 254 }
Chris@376 255 }
Chris@376 256
Chris@376 257 QPixmap
Chris@376 258 ColourDatabase::getExamplePixmap(int index, QSize size) const
Chris@376 259 {
Chris@376 260 QPixmap pmap(size);
Chris@376 261 pmap.fill(useDarkBackground(index) ? Qt::black : Qt::white);
Chris@376 262 QPainter paint(&pmap);
Chris@376 263 QColor colour(getColour(index));
Chris@376 264 paint.setPen(colour);
Chris@376 265 paint.setBrush(colour);
Chris@376 266 int margin = 2;
Chris@376 267 if (size.width() < 4 || size.height() < 4) margin = 0;
Chris@376 268 else if (size.width() < 8 || size.height() < 8) margin = 1;
Chris@376 269 paint.drawRect(margin, margin,
Chris@376 270 size.width() - margin*2 - 1, size.height() - margin*2 - 1);
Chris@376 271 return pmap;
Chris@376 272 }
Chris@376 273