Tue, 15 Nov 2016 13:52:44 +0200
Cleanup colors.cpp/.h
src/colors.cpp | file | annotate | diff | comparison | revisions | |
src/colors.h | file | annotate | diff | comparison | revisions |
--- a/src/colors.cpp Fri Nov 11 13:59:27 2016 +0200 +++ b/src/colors.cpp Tue Nov 15 13:52:44 2016 +0200 @@ -28,6 +28,11 @@ static ColorData* colorData = nullptr; +/* + * initColors + * + * Initializes the color information module. + */ void initColors() { print ("Initializing color information.\n"); @@ -35,24 +40,61 @@ colorData = &colors; } +/* + * LDColor :: LDColor + * + * Default-constructs an LDColor to 0 (black). + */ +LDColor::LDColor() : + m_index (0) {} + +/* + * LDColor :: LDColor + * + * Constructs an LDColor by index. + */ +LDColor::LDColor (qint32 index) + : m_index (index) {} + +/* + * LDColor :: isValid + * + * Returns whether or not the color is valid. + */ bool LDColor::isValid() const { if (isLDConfigColor() and data().name.isEmpty()) return false; // Unknown LDConfig color - - return m_index != -1; + else + return m_index != -1; } +/* + * LDColor :: isLDConfigColor + * + * Returns whether or not this color is defined in LDConfig.ldr. + * This is false for e.g. direct colors. + */ bool LDColor::isLDConfigColor() const { - return colorData->contains (index()); + return colorData->contains(index()); } +/* + * LDColor :: data + * + * Returns the ColorData entry for this color. + */ const ColorData::Entry& LDColor::data() const { - return colorData->get (index()); + return colorData->get(index()); } +/* + * LDColor :: name + * + * Returns the name of this color. + */ QString LDColor::name() const { if (isDirect()) @@ -62,25 +104,36 @@ else if (index() == -1) return "null color"; else - return ""; + return "unknown"; } +/* + * LDColor :: hexcode + * + * Returns the hexadecimal code of this color. + */ QString LDColor::hexcode() const { return faceColor().name(); } +/* + * LDColor :: faceColor + * + * Returns the color used for surfaces. + */ QColor LDColor::faceColor() const { if (isDirect()) { + // Direct color -- compute from the index. QColor color; - color.setRed ((index() & 0x0FF0000) >> 16); - color.setGreen ((index() & 0x000FF00) >> 8); - color.setBlue (index() & 0x00000FF); + color.setRed((index() & 0x0FF0000) >> 16); + color.setGreen((index() & 0x000FF00) >> 8); + color.setBlue(index() & 0x00000FF); if (index() >= 0x3000000) - color.setAlpha (128); + color.setAlpha(128); return color; } @@ -94,184 +147,263 @@ } } +/* + * LDColor :: edgeColor + * + * Returns the color used for edge lines. + */ QColor LDColor::edgeColor() const { if (isDirect()) - return ::luma (faceColor()) < 48 ? Qt::white : Qt::black; + return luma(faceColor()) < 48 ? Qt::white : Qt::black; else if (isLDConfigColor()) return data().edgeColor; else return Qt::black; } -int LDColor::luma() const -{ - return ::luma (faceColor()); -} - -int LDColor::edgeLuma() const -{ - return ::luma (edgeColor()); -} - +/* + * LDColor :: index + * + * Returns the index number of this color. + */ qint32 LDColor::index() const { return m_index; } +/* + * LDColor :: indexString + * + * Returns a string containing the preferred representation of the index. + */ QString LDColor::indexString() const { if (isDirect()) - return "0x" + QString::number (index(), 16).toUpper(); - - return QString::number (index()); + { + // Use hexadecimal notation for direct colors. + return "0x" + QString::number(index(), 16).toUpper(); + } + else + { + return QString::number(index()); + } } +/* + * LDColor :: isDirect + * + * Returns whether or not this color is a direct color. + * Direct colors are picked by RGB value and are not defined in LDConfig.ldr. + */ bool LDColor::isDirect() const { return index() >= 0x02000000; } +/* + * LDColor :: nullColor + * + * Returns a color that is guaranteed to be invalid. + */ +LDColor LDColor::nullColor() +{ + return LDColor {-1}; +} + +/* + * qHash + * + * LDColors are hashed by their index. + */ uint qHash(LDColor color) { return color.index(); } -int luma (const QColor& col) +/* + * luma + * + * Calculates the luma-value for the given color. + * c.f. https://en.wikipedia.org/wiki/Luma_(video) + */ +int luma (const QColor& color) { - return (0.2126f * col.red()) + (0.7152f * col.green()) + (0.0722f * col.blue()); + return round((0.2126 * color.red()) + (0.7152 * color.green()) + (0.0722 * color.blue())); } +/* + * ColorData :: ColorData + * + * Constructs the color data array. + */ ColorData::ColorData() { if (colorData == nullptr) colorData = this; // Initialize main and edge colors, they're special like that. - m_data[MainColor].faceColor = - m_data[MainColor].hexcode = "#AAAAAA"; + m_data[MainColor].faceColor = "#AAAAAA"; m_data[MainColor].edgeColor = Qt::black; m_data[MainColor].name = "Main color"; m_data[EdgeColor].faceColor = - m_data[EdgeColor].edgeColor = - m_data[EdgeColor].hexcode = "#000000"; + m_data[EdgeColor].edgeColor = "#000000"; m_data[EdgeColor].name = "Edge color"; + + // Load the rest from LDConfig.ldr. loadFromLdconfig(); } +/* + * ColorData :: ~ColorData + * + * Cleanup the colorData pointer after the array is deleted. + */ ColorData::~ColorData() { if (colorData == this) colorData = nullptr; } -bool ColorData::contains (int code) const +/* + * ColorData :: contains + * + * Returns whether or not the given color index is present in the array. + */ +bool ColorData::contains(int code) const { - return code >= 0 and code < EntryCount; + return code >= 0 and code < countof(m_data); } -const ColorData::Entry& ColorData::get (int code) const +/* + * ColorData :: get + * + * Returns an entry in the color array. + */ +const ColorData::Entry& ColorData::get(int code) const { - if (not contains (code)) - throw std::runtime_error ("Attempted to get non-existant color information"); + if (not contains(code)) + throw std::runtime_error {"Attempted to get non-existant color information"}; return m_data[code]; } +/* + * ColorData :: loadFromLdconfig + * + * Loads color information from LDConfig.ldr. + */ void ColorData::loadFromLdconfig() { QString path = LDPaths::ldConfigPath(); - QFile fp (path); + QFile file {path}; - if (not fp.open (QIODevice::ReadOnly)) + if (not file.open (QIODevice::ReadOnly)) { - QMessageBox::critical (nullptr, "Error", "Unable to open LDConfig.ldr for parsing: " + fp.errorString()); + QMessageBox::critical(nullptr, "Error", "Unable to open LDConfig.ldr for parsing: " + file.errorString()); return; } // TODO: maybe LDConfig can be loaded as a Document? Or would that be overkill? - while (not fp.atEnd()) + while (not file.atEnd()) { - QString line = QString::fromUtf8 (fp.readLine()); + QString line = QString::fromUtf8 (file.readLine()); if (line.isEmpty() or line[0] != '0') continue; // empty or illogical - line.remove ('\r'); - line.remove ('\n'); + line.remove('\r'); + line.remove('\n'); // Parse the line - LDConfigParser parser (line, ' '); + LDConfigParser parser = {line}; QString name; QString facename; QString edgename; QString codestring; // Check 0 !COLOUR, parse the name - if (not parser.compareToken (0, "0") or not parser.compareToken (1, "!COLOUR") or not parser.getToken (name, 2)) + if (not parser.compareToken(0, "0") or not parser.compareToken(1, "!COLOUR") or not parser.getToken(name, 2)) continue; // Replace underscores in the name with spaces for readability - name.replace ("_", " "); + name.replace("_", " "); if (not parser.parseTag ("CODE", codestring)) continue; bool ok; - int code = codestring.toShort (&ok); + int code = codestring.toShort(&ok); - if (not ok or not contains (code)) + if (not ok or not contains(code)) continue; - if (not parser.parseTag ("VALUE", facename) or not parser.parseTag ("EDGE", edgename)) + if (not parser.parseTag("VALUE", facename) or not parser.parseTag("EDGE", edgename)) continue; // Ensure that our colors are correct - QColor faceColor (facename); - QColor edgeColor (edgename); + QColor faceColor = {facename}; + QColor edgeColor = {edgename}; if (not faceColor.isValid() or not edgeColor.isValid()) continue; + // Fill in the entry now. Entry& entry = m_data[code]; entry.name = name; entry.faceColor = faceColor; entry.edgeColor = edgeColor; - entry.hexcode = facename; - if (parser.parseTag ("ALPHA", codestring)) - entry.faceColor.setAlpha (qBound (0, codestring.toInt(), 255)); + // If the alpha tag is present, fill in that too. + if (parser.parseTag("ALPHA", codestring)) + entry.faceColor.setAlpha(qBound(0, codestring.toInt(), 255)); } } -// ============================================================================= -// -LDConfigParser::LDConfigParser (QString inText, char sep) +/* + * LDConfigParser :: LDConfigParser + * + * Constructs the LDConfig.ldr parser. + */ +LDConfigParser::LDConfigParser(QString inputText) { - m_tokens = inText.split (sep, QString::SkipEmptyParts); - m_pos = -1; + m_tokens = inputText.split (' ', QString::SkipEmptyParts); } -// ============================================================================= -// -bool LDConfigParser::getToken (QString& val, const int pos) +/* + * LDConfigParser :: getToken + * + * Returns whether or not there is a token at the given position. + * If there is, fills in the value parameter with it. + */ +bool LDConfigParser::getToken(QString& tokenText, int position) { - if (pos >= m_tokens.size()) + if (position >= m_tokens.size()) + { return false; - - val = m_tokens[pos]; - return true; + } + else + { + tokenText = m_tokens[position]; + return true; + } } -// ============================================================================= -// -bool LDConfigParser::findToken (int& result, char const* needle, int args) +/* + * LDConfigParser :: findToken + * + * Attempts to find the provided token in the parsed LDConfig.ldr line. + * If found, fills in the first parameter with the position of the token. + * + * The args parameter specifies how many arguments (i.e. following tokens) the token needs to have. + */ +bool LDConfigParser::findToken(int& tokenPosition, QString needle, int args) { for (int i = 0; i < (m_tokens.size() - args); ++i) { if (m_tokens[i] == needle) { - result = i; + tokenPosition = i; return true; } } @@ -279,30 +411,40 @@ return false; } -// ============================================================================= -// -bool LDConfigParser::compareToken (int inPos, QString text) +/* + * LDConfigParser :: compareToken + * + * Returns whether or not the token at the given position has the given text value. + */ +bool LDConfigParser::compareToken (int position, QString text) { - QString tok; + QString token; - if (not getToken (tok, inPos)) + if (not getToken(token, position)) return false; - - return (tok == text); + else + return (token == text); } -// ============================================================================= -// -// Helper function for parseLDConfig -// -bool LDConfigParser::parseTag (char const* tag, QString& val) +/* + * LDConfig :: parseTag + * + * Finds an attribute in the line, and fills in its value. + * For instance, if the line contains "ALPHA 128", this function can find the "128" for "ALPHA". + * Returns whether or not the attribute was found. + */ +bool LDConfigParser::parseTag (QString key, QString& value) { - int pos; + int position; // Try find the token and get its position - if (not findToken (pos, tag, 1)) + if (not findToken (position, key, 1)) + { return false; - - // Get the token after it and store it into val - return getToken (val, pos + 1); -} \ No newline at end of file + } + else + { + // Get the token after it and store it in. + return getToken (value, position + 1); + } +}
--- a/src/colors.h Fri Nov 11 13:59:27 2016 +0200 +++ b/src/colors.h Tue Nov 15 13:52:44 2016 +0200 @@ -20,34 +20,43 @@ #include <QColor> #include "basics.h" +/* + * ColorData + * + * This class contains the model data for LDConfig-defined colors. + */ class ColorData { public: struct Entry { QString name; - QString hexcode; QColor faceColor; QColor edgeColor; }; - enum { EntryCount = 512 }; ColorData(); ~ColorData(); void loadFromLdconfig(); - bool contains (int code) const; - const Entry& get (int code) const; + bool contains(int code) const; + const Entry& get(int code) const; private: - Entry m_data[EntryCount]; + Entry m_data[512]; }; +/* + * LDColor + * + * This class represents an LDraw color. For a color index, this class provides information for that color. + * It only contains the index of the color. Therefore it is a wrapper around an integer and should be passed by value. + */ class LDColor { public: - LDColor() : m_index (0) {} - LDColor (qint32 index) : m_index (index) {} - LDColor (const LDColor& other) : m_index (other.m_index) {} + LDColor(); + LDColor(qint32 index); + LDColor(const LDColor& other) = default; bool isLDConfigColor() const; bool isValid() const; @@ -56,26 +65,23 @@ QColor faceColor() const; QColor edgeColor() const; qint32 index() const; - int luma() const; - int edgeLuma() const; bool isDirect() const; QString indexString() const; - static LDColor nullColor() { return LDColor (-1); } + static LDColor nullColor(); - LDColor& operator= (qint32 index) { m_index = index; return *this; } - LDColor& operator= (LDColor other) { m_index = other.index(); return *this; } + LDColor& operator=(qint32 index) { m_index = index; return *this; } + LDColor& operator=(const LDColor &other) = default; LDColor operator++() { return ++m_index; } - LDColor operator++ (int) { return m_index++; } + LDColor operator++(int) { return m_index++; } LDColor operator--() { return --m_index; } - LDColor operator-- (int) { return m_index--; } - - bool operator== (LDColor other) const { return index() == other.index(); } - bool operator!= (LDColor other) const { return index() != other.index(); } - bool operator< (LDColor other) const { return index() < other.index(); } - bool operator<= (LDColor other) const { return index() <= other.index(); } - bool operator> (LDColor other) const { return index() > other.index(); } - bool operator>= (LDColor other) const { return index() >= other.index(); } + LDColor operator--(int) { return m_index--; } + bool operator==(LDColor other) const { return index() == other.index(); } + bool operator!=(LDColor other) const { return index() != other.index(); } + bool operator<(LDColor other) const { return index() < other.index(); } + bool operator<=(LDColor other) const { return index() <= other.index(); } + bool operator>(LDColor other) const { return index() > other.index(); } + bool operator>=(LDColor other) const { return index() >= other.index(); } private: const ColorData::Entry& data() const; @@ -85,31 +91,27 @@ uint qHash(LDColor color); -// -// Parses ldconfig.ldr -// +/* + * LDConfigParser + * + * Parses LDConfig.ldr. + */ class LDConfigParser { public: - LDConfigParser (QString inText, char sep); + LDConfigParser(QString inputText); - bool getToken (QString& val, const int pos); - bool findToken (int& result, char const* needle, int args); - bool compareToken (int inPos, QString text); - bool parseTag (char const* tag, QString& val); - - inline QString operator[] (const int idx) - { - return m_tokens[idx]; - } + bool getToken(QString& tokenText, int position); + bool findToken(int& tokenPosition, QString needle, int args); + bool compareToken(int inPos, QString text); + bool parseTag(QString key, QString& value); private: QStringList m_tokens; - int m_pos; }; void initColors(); -int luma (const QColor& col); +int luma(const QColor& col); enum {