16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 */ |
17 */ |
18 |
18 |
19 #include "colors.h" |
19 #include "colors.h" |
20 |
20 |
21 const ldraw::ColorTable::ColorDefinition ldraw::ColorTable::unknownColor{{}, {}, "Unknown", "???"}; |
21 const ldraw::ColorDefinition ldraw::ColorTable::unknownColor{{}, {}, "Unknown", "???"}; |
22 |
22 |
|
23 /** |
|
24 * @brief Clears the color table |
|
25 */ |
23 void ldraw::ColorTable::clear() |
26 void ldraw::ColorTable::clear() |
24 { |
27 { |
25 definitions = {}; |
28 this->definitions = {}; |
26 } |
29 } |
27 |
30 |
|
31 /** |
|
32 * @brief Loads colors from LDConfig.ldr |
|
33 * @param device Opened LDConfig.ldr I/O device |
|
34 * @param errors Where to write any errors into |
|
35 * @returns whether or not it succeeded. |
|
36 */ |
28 Result ldraw::ColorTable::load(QIODevice& device, QTextStream& errors) |
37 Result ldraw::ColorTable::load(QIODevice& device, QTextStream& errors) |
29 { |
38 { |
30 this->clear(); |
39 this->clear(); |
31 if (device.isReadable()) |
40 if (device.isReadable()) |
32 { |
41 { |
43 errors << "could not read colors"; |
52 errors << "could not read colors"; |
44 return Failure; |
53 return Failure; |
45 } |
54 } |
46 } |
55 } |
47 |
56 |
48 const ldraw::ColorTable::ColorDefinition& ldraw::ColorTable::operator[](Color color) const |
57 /** |
|
58 * @brief Gets color information by color index. |
|
59 * @param color |
|
60 * @returns color table information |
|
61 */ |
|
62 const ldraw::ColorDefinition& ldraw::ColorTable::operator[](Color color) const |
49 { |
63 { |
50 auto it = this->definitions.find(color.index); |
64 auto it = this->definitions.find(color.index); |
51 if (it != this->definitions.end()) |
65 if (it != this->definitions.end()) |
52 { |
66 { |
53 return it->second; |
67 return it->second; |
56 { |
70 { |
57 return unknownColor; |
71 return unknownColor; |
58 } |
72 } |
59 } |
73 } |
60 |
74 |
|
75 /** |
|
76 * @brief Gets the amount of elements in the color table |
|
77 * @returns int |
|
78 */ |
|
79 int ldraw::ColorTable::size() const |
|
80 { |
|
81 return this->definitions.size(); |
|
82 } |
|
83 |
|
84 /** |
|
85 * @brief Parses an LDConfig.ldr line from a string |
|
86 * @param string LDConfig.ldr line to parse |
|
87 */ |
61 void ldraw::ColorTable::loadColorFromString(const QString& string) |
88 void ldraw::ColorTable::loadColorFromString(const QString& string) |
62 { |
89 { |
63 const QRegExp pattern{ |
90 const QRegExp pattern{ |
64 R"(^\s*0 \!COLOUR\s+([^\s]+)\s+)"_q + |
91 R"(^\s*0 \!COLOUR\s+([^\s]+)\s+)"_q + |
65 R"(CODE\s+(\d+)\s+)"_q + |
92 R"(CODE\s+(\d+)\s+)"_q + |
68 R"((?:\s+ALPHA\s+(\d+))?)"_q |
95 R"((?:\s+ALPHA\s+(\d+))?)"_q |
69 }; |
96 }; |
70 if (pattern.indexIn(string) != -1) |
97 if (pattern.indexIn(string) != -1) |
71 { |
98 { |
72 const int code = pattern.cap(2).toInt(); |
99 const int code = pattern.cap(2).toInt(); |
73 ColorDefinition& definition = definitions[code]; |
100 ColorDefinition& definition = this->definitions[code]; |
74 definition = {}; // in case there's an existing definition |
101 definition = {}; // in case there's an existing definition |
75 definition.name = pattern.cap(1); |
102 definition.name = pattern.cap(1); |
76 definition.displayName = definition.name; |
103 definition.displayName = definition.name; |
77 definition.displayName.replace("_", " "); |
104 definition.displayName.replace("_", " "); |
78 definition.faceColor = pattern.cap(3); |
105 definition.faceColor = pattern.cap(3); |
83 definition.faceColor.setAlpha(alpha); |
110 definition.faceColor.setAlpha(alpha); |
84 } |
111 } |
85 } |
112 } |
86 } |
113 } |
87 |
114 |
88 /* |
115 /** |
89 * Calculates the luma-value for the given color. |
116 * @brief Calculates the luma-value for the given color. |
90 * c.f. https://en.wikipedia.org/wiki/Luma_(video) |
117 * @details c.f. https://en.wikipedia.org/wiki/Luma_(video) |
|
118 * @param color |
|
119 * @returns luma value [0, 1] |
91 */ |
120 */ |
92 double luma(const QColor& color) |
121 double luma(const QColor& color) |
93 { |
122 { |
94 return 0.2126 * color.redF() + 0.7152 * color.greenF() + 0.0722 * color.blueF(); |
123 return 0.2126 * color.redF() + 0.7152 * color.greenF() + 0.0722 * color.blueF(); |
95 } |
124 } |
96 |
125 |
|
126 /** |
|
127 * @brief Returns a direct color index that codes the specified color value |
|
128 * @param color |
|
129 * @returns direct color index |
|
130 */ |
97 ldraw::Color ldraw::directColor(const QColor& color) |
131 ldraw::Color ldraw::directColor(const QColor& color) |
98 { |
132 { |
99 return ldraw::Color{0x2000000 | (color.red() << 16) | (color.green() << 8) | color.blue()}; |
133 return ldraw::Color{0x2000000 | (color.red() << 16) | (color.green() << 8) | color.blue()}; |
100 } |
134 } |
101 |
135 |
|
136 /** |
|
137 * @brief Checks whether or not the specified color index is a direct color |
|
138 * @param color Color to check |
|
139 * @returns bool |
|
140 */ |
102 bool ldraw::isDirectColor(ldraw::Color color) |
141 bool ldraw::isDirectColor(ldraw::Color color) |
103 { |
142 { |
104 return color.index >= 0x2000000; |
143 return color.index >= 0x2000000; |
105 } |
144 } |
106 |
145 |
|
146 /** |
|
147 * @brief Extracts the color value from a direct color index |
|
148 * @param color Direct color index |
|
149 * @returns color value. Returns a default-constructed QColor in case a non-direct color is given. |
|
150 */ |
107 QColor ldraw::directColorFace(ldraw::Color color) |
151 QColor ldraw::directColorFace(ldraw::Color color) |
108 { |
152 { |
109 if (isDirectColor(color)) |
153 if (isDirectColor(color)) |
110 { |
154 { |
111 return {(color.index >> 16) & 0xff, (color.index >> 8) & 0xff, color.index & 0xff}; |
155 return {(color.index >> 16) & 0xff, (color.index >> 8) & 0xff, color.index & 0xff}; |
114 { |
158 { |
115 return {}; |
159 return {}; |
116 } |
160 } |
117 } |
161 } |
118 |
162 |
|
163 /** |
|
164 * @brief Gets the face color for the specified color index |
|
165 * @param color Color index to get face color for |
|
166 * @param colorTable Color table to use for lookup |
|
167 * @returns QColor |
|
168 */ |
119 QColor ldraw::colorFace(ldraw::Color color, const ldraw::ColorTable& colorTable) |
169 QColor ldraw::colorFace(ldraw::Color color, const ldraw::ColorTable& colorTable) |
120 { |
170 { |
121 if (isDirectColor(color)) |
171 if (isDirectColor(color)) |
122 { |
172 { |
123 return directColorFace(color); |
173 return directColorFace(color); |
126 { |
176 { |
127 return colorTable[color].faceColor; |
177 return colorTable[color].faceColor; |
128 } |
178 } |
129 } |
179 } |
130 |
180 |
|
181 /** |
|
182 * @brief Writes a color index into a @c QDataStream |
|
183 * @param stream |
|
184 * @param color |
|
185 * @returns stream |
|
186 */ |
131 QDataStream& operator<<(QDataStream& stream, ldraw::Color color) |
187 QDataStream& operator<<(QDataStream& stream, ldraw::Color color) |
132 { |
188 { |
133 return stream << color.index; |
189 return stream << color.index; |
134 } |
190 } |
135 |
191 |
|
192 /** |
|
193 * @brief Reads a color index from a @c QDataStream |
|
194 * @param stream |
|
195 * @param color |
|
196 * @returns stream |
|
197 */ |
136 QDataStream& operator>>(QDataStream& stream, ldraw::Color& color) |
198 QDataStream& operator>>(QDataStream& stream, ldraw::Color& color) |
137 { |
199 { |
138 return stream >> color.index; |
200 return stream >> color.index; |
139 } |
201 } |