src/colors.cpp

changeset 952
f116b63c4844
parent 946
9cbd658b63f9
child 962
a4b463a7ee82
equal deleted inserted replaced
950:5df69eb50182 952:f116b63c4844
1 /*
2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2013, 2014 Teemu Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <QFile>
20 #include "main.h"
21 #include "colors.h"
22 #include "ldDocument.h"
23 #include "miscallenous.h"
24 #include "mainWindow.h"
25
26 struct ColorDataEntry
27 {
28 QString name;
29 QString hexcode;
30 QColor faceColor;
31 QColor edgeColor;
32 };
33
34 static ColorDataEntry ColorData[512];
35
36 void InitColors()
37 {
38 print ("Initializing color information.\n");
39
40 // Always make sure there's 16 and 24 available. They're special like that.
41 ColorData[MainColor].faceColor =
42 ColorData[MainColor].hexcode = "#AAAAAA";
43 ColorData[MainColor].edgeColor = Qt::black;
44 ColorData[MainColor].name = "Main color";
45
46 ColorData[EdgeColor].faceColor =
47 ColorData[EdgeColor].edgeColor =
48 ColorData[EdgeColor].hexcode = "#000000";
49 ColorData[EdgeColor].name = "Edge color";
50
51 parseLDConfig();
52 }
53
54 bool LDColor::isValid() const
55 {
56 if (isLDConfigColor() and ColorData[index()].name.isEmpty())
57 return false; // Unknown LDConfig color
58
59 return m_index != -1;
60 }
61
62 bool LDColor::isLDConfigColor() const
63 {
64 return index() >= 0 and index() < countof (ColorData);
65 }
66
67 QString LDColor::name() const
68 {
69 if (isDirect())
70 return "0x" + QString::number (index(), 16).toUpper();
71 else if (isLDConfigColor())
72 return ColorData[index()].name;
73 else if (index() == -1)
74 return "null color";
75 else
76 return "";
77 }
78
79 QString LDColor::hexcode() const
80 {
81 return faceColor().name();
82 }
83
84 QColor LDColor::faceColor() const
85 {
86 if (isDirect())
87 {
88 QColor color;
89 color.setRed ((index() & 0x0FF0000) >> 16);
90 color.setGreen ((index() & 0x000FF00) >> 8);
91 color.setBlue (index() & 0x00000FF);
92
93 if (index() >= 0x3000000)
94 color.setAlpha (128);
95
96 return color;
97 }
98 else if (isLDConfigColor())
99 {
100 return ColorData[index()].faceColor;
101 }
102 else
103 {
104 return Qt::black;
105 }
106 }
107
108 QColor LDColor::edgeColor() const
109 {
110 if (isDirect())
111 return Luma (faceColor()) < 48 ? Qt::white : Qt::black;
112 else if (isLDConfigColor())
113 return ColorData[index()].edgeColor;
114 else
115 return Qt::black;
116 }
117
118 int LDColor::luma() const
119 {
120 return Luma (faceColor());
121 }
122
123 int LDColor::edgeLuma() const
124 {
125 return Luma (edgeColor());
126 }
127
128 qint32 LDColor::index() const
129 {
130 return m_index;
131 }
132
133 QString LDColor::indexString() const
134 {
135 if (isDirect())
136 return "0x" + QString::number (index(), 16).toUpper();
137
138 return QString::number (index());
139 }
140
141 bool LDColor::isDirect() const
142 {
143 return index() >= 0x02000000;
144 }
145
146 int Luma (const QColor& col)
147 {
148 return (0.2126f * col.red()) + (0.7152f * col.green()) + (0.0722f * col.blue());
149 }
150
151 int CountLDConfigColors()
152 {
153 return countof (ColorData);
154 }
155
156 void parseLDConfig()
157 {
158 QFile* fp = OpenLDrawFile ("LDConfig.ldr", false);
159
160 if (fp == nullptr)
161 {
162 Critical (QObject::tr ("Unable to open LDConfig.ldr for parsing."));
163 return;
164 }
165
166 // Read in the lines
167 while (not fp->atEnd())
168 {
169 QString line = QString::fromUtf8 (fp->readLine());
170
171 if (line.isEmpty() or line[0] != '0')
172 continue; // empty or illogical
173
174 line.remove ('\r');
175 line.remove ('\n');
176
177 // Parse the line
178 LDConfigParser pars (line, ' ');
179
180 int code = 0, alpha = 255;
181 QString name, facename, edgename, valuestr;
182
183 // Check 0 !COLOUR, parse the name
184 if (not pars.compareToken (0, "0") or
185 not pars.compareToken (1, "!COLOUR") or
186 not pars.getToken (name, 2))
187 {
188 continue;
189 }
190
191 // Replace underscores in the name with spaces for readability
192 name.replace ("_", " ");
193
194 // Get the CODE tag
195 if (not pars.parseLDConfigTag ("CODE", valuestr))
196 continue;
197
198 // Ensure that the code is within [0 - 511]
199 bool ok;
200 code = valuestr.toShort (&ok);
201
202 if (not ok or code < 0 or code >= 512)
203 continue;
204
205 // VALUE and EDGE tags
206 if (not pars.parseLDConfigTag ("VALUE", facename) or not pars.parseLDConfigTag ("EDGE", edgename))
207 continue;
208
209 // Ensure that our colors are correct
210 QColor faceColor (facename),
211 edgeColor (edgename);
212
213 if (not faceColor.isValid() or not edgeColor.isValid())
214 continue;
215
216 // Parse alpha if given.
217 if (pars.parseLDConfigTag ("ALPHA", valuestr))
218 alpha = Clamp (valuestr.toInt(), 0, 255);
219
220 ColorDataEntry& entry = ColorData[code];
221 entry.name = name;
222 entry.faceColor = faceColor;
223 entry.edgeColor = edgeColor;
224 entry.hexcode = facename;
225 entry.faceColor.setAlpha (alpha);
226 }
227
228 fp->close();
229 fp->deleteLater();
230 }
231
232 // =============================================================================
233 //
234 LDConfigParser::LDConfigParser (QString inText, char sep)
235 {
236 m_tokens = inText.split (sep, QString::SkipEmptyParts);
237 m_pos = -1;
238 }
239
240 // =============================================================================
241 //
242 bool LDConfigParser::getToken (QString& val, const int pos)
243 {
244 if (pos >= m_tokens.size())
245 return false;
246
247 val = m_tokens[pos];
248 return true;
249 }
250
251 // =============================================================================
252 //
253 bool LDConfigParser::findToken (int& result, char const* needle, int args)
254 {
255 for (int i = 0; i < (m_tokens.size() - args); ++i)
256 {
257 if (m_tokens[i] == needle)
258 {
259 result = i;
260 return true;
261 }
262 }
263
264 return false;
265 }
266
267 // =============================================================================
268 //
269 bool LDConfigParser::compareToken (int inPos, QString text)
270 {
271 QString tok;
272
273 if (not getToken (tok, inPos))
274 return false;
275
276 return (tok == text);
277 }
278
279 // =============================================================================
280 //
281 // Helper function for parseLDConfig
282 //
283 bool LDConfigParser::parseLDConfigTag (char const* tag, QString& val)
284 {
285 int pos;
286
287 // Try find the token and get its position
288 if (not findToken (pos, tag, 1))
289 return false;
290
291 // Get the token after it and store it into val
292 return getToken (val, pos + 1);
293 }

mercurial