Sun, 04 Oct 2015 06:43:02 +0300
Bézier curves are now parsed correctly
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
1 | /* |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
2 | * LDForge: LDraw parts authoring CAD |
968 | 3 | * Copyright (C) 2013 - 2015 Teemu Piippo |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
4 | * |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
5 | * This program is free software: you can redistribute it and/or modify |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
6 | * it under the terms of the GNU General Public License as published by |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
7 | * the Free Software Foundation, either version 3 of the License, or |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
8 | * (at your option) any later version. |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
9 | * |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
10 | * This program is distributed in the hope that it will be useful, |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
13 | * GNU General Public License for more details. |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
14 | * |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
15 | * You should have received a copy of the GNU General Public License |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
17 | */ |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
18 | |
946 | 19 | #include <QFile> |
998 | 20 | #include <QMessageBox> |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
21 | #include "main.h" |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
22 | #include "colors.h" |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
23 | #include "ldDocument.h" |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
24 | #include "miscallenous.h" |
962
a4b463a7ee82
Rename MainWindow files
Teemu Piippo <crimsondusk64@gmail.com>
parents:
952
diff
changeset
|
25 | #include "mainwindow.h" |
998 | 26 | #include "documentmanager.h" |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
27 | |
998 | 28 | static ColorData* colorData = nullptr; |
946 | 29 | |
998 | 30 | void initColors() |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
31 | { |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
32 | print ("Initializing color information.\n"); |
998 | 33 | static ColorData colors; |
34 | colorData = &colors; | |
946 | 35 | } |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
36 | |
946 | 37 | bool LDColor::isValid() const |
38 | { | |
998 | 39 | if (isLDConfigColor() and data().name.isEmpty()) |
946 | 40 | return false; // Unknown LDConfig color |
41 | ||
42 | return m_index != -1; | |
795
195fa1fff9c3
- changed all color usage to use LDColor classes instead of color indices. Added support for direct colors.
Santeri Piippo <crimsondusk64@gmail.com>
parents:
706
diff
changeset
|
43 | } |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
44 | |
946 | 45 | bool LDColor::isLDConfigColor() const |
795
195fa1fff9c3
- changed all color usage to use LDColor classes instead of color indices. Added support for direct colors.
Santeri Piippo <crimsondusk64@gmail.com>
parents:
706
diff
changeset
|
46 | { |
998 | 47 | return colorData->contains (index()); |
48 | } | |
49 | ||
50 | const ColorData::Entry& LDColor::data() const | |
51 | { | |
52 | return colorData->get (index()); | |
795
195fa1fff9c3
- changed all color usage to use LDColor classes instead of color indices. Added support for direct colors.
Santeri Piippo <crimsondusk64@gmail.com>
parents:
706
diff
changeset
|
53 | } |
195fa1fff9c3
- changed all color usage to use LDColor classes instead of color indices. Added support for direct colors.
Santeri Piippo <crimsondusk64@gmail.com>
parents:
706
diff
changeset
|
54 | |
946 | 55 | QString LDColor::name() const |
795
195fa1fff9c3
- changed all color usage to use LDColor classes instead of color indices. Added support for direct colors.
Santeri Piippo <crimsondusk64@gmail.com>
parents:
706
diff
changeset
|
56 | { |
946 | 57 | if (isDirect()) |
58 | return "0x" + QString::number (index(), 16).toUpper(); | |
59 | else if (isLDConfigColor()) | |
998 | 60 | return data().name; |
946 | 61 | else if (index() == -1) |
62 | return "null color"; | |
63 | else | |
64 | return ""; | |
65 | } | |
66 | ||
67 | QString LDColor::hexcode() const | |
68 | { | |
69 | return faceColor().name(); | |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
70 | } |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
71 | |
946 | 72 | QColor LDColor::faceColor() const |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
73 | { |
946 | 74 | if (isDirect()) |
75 | { | |
76 | QColor color; | |
77 | color.setRed ((index() & 0x0FF0000) >> 16); | |
78 | color.setGreen ((index() & 0x000FF00) >> 8); | |
79 | color.setBlue (index() & 0x00000FF); | |
80 | ||
81 | if (index() >= 0x3000000) | |
82 | color.setAlpha (128); | |
83 | ||
84 | return color; | |
85 | } | |
86 | else if (isLDConfigColor()) | |
87 | { | |
998 | 88 | return data().faceColor; |
946 | 89 | } |
90 | else | |
91 | { | |
92 | return Qt::black; | |
93 | } | |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
94 | } |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
95 | |
946 | 96 | QColor LDColor::edgeColor() const |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
97 | { |
946 | 98 | if (isDirect()) |
998 | 99 | return ::luma (faceColor()) < 48 ? Qt::white : Qt::black; |
946 | 100 | else if (isLDConfigColor()) |
998 | 101 | return data().edgeColor; |
946 | 102 | else |
103 | return Qt::black; | |
104 | } | |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
105 | |
946 | 106 | int LDColor::luma() const |
107 | { | |
998 | 108 | return ::luma (faceColor()); |
946 | 109 | } |
795
195fa1fff9c3
- changed all color usage to use LDColor classes instead of color indices. Added support for direct colors.
Santeri Piippo <crimsondusk64@gmail.com>
parents:
706
diff
changeset
|
110 | |
946 | 111 | int LDColor::edgeLuma() const |
112 | { | |
998 | 113 | return ::luma (edgeColor()); |
946 | 114 | } |
795
195fa1fff9c3
- changed all color usage to use LDColor classes instead of color indices. Added support for direct colors.
Santeri Piippo <crimsondusk64@gmail.com>
parents:
706
diff
changeset
|
115 | |
946 | 116 | qint32 LDColor::index() const |
117 | { | |
118 | return m_index; | |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
119 | } |
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
120 | |
806
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
121 | QString LDColor::indexString() const |
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
122 | { |
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
123 | if (isDirect()) |
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
124 | return "0x" + QString::number (index(), 16).toUpper(); |
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
125 | |
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
126 | return QString::number (index()); |
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
127 | } |
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
128 | |
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
129 | bool LDColor::isDirect() const |
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
130 | { |
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
131 | return index() >= 0x02000000; |
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
132 | } |
4240f47aa2d4
- moved most of LDColorData API into LDColor
Santeri Piippo <crimsondusk64@gmail.com>
parents:
797
diff
changeset
|
133 | |
998 | 134 | int luma (const QColor& col) |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
135 | { |
946 | 136 | return (0.2126f * col.red()) + (0.7152f * col.green()) + (0.0722f * col.blue()); |
655
b376645315ab
- renamed files to camelCase
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff
changeset
|
137 | } |
795
195fa1fff9c3
- changed all color usage to use LDColor classes instead of color indices. Added support for direct colors.
Santeri Piippo <crimsondusk64@gmail.com>
parents:
706
diff
changeset
|
138 | |
998 | 139 | ColorData::ColorData() |
795
195fa1fff9c3
- changed all color usage to use LDColor classes instead of color indices. Added support for direct colors.
Santeri Piippo <crimsondusk64@gmail.com>
parents:
706
diff
changeset
|
140 | { |
998 | 141 | if (colorData == nullptr) |
142 | colorData = this; | |
143 | ||
144 | // Initialize main and edge colors, they're special like that. | |
145 | m_data[MainColor].faceColor = | |
146 | m_data[MainColor].hexcode = "#AAAAAA"; | |
147 | m_data[MainColor].edgeColor = Qt::black; | |
148 | m_data[MainColor].name = "Main color"; | |
149 | m_data[EdgeColor].faceColor = | |
150 | m_data[EdgeColor].edgeColor = | |
151 | m_data[EdgeColor].hexcode = "#000000"; | |
152 | m_data[EdgeColor].name = "Edge color"; | |
153 | loadFromLdconfig(); | |
154 | } | |
155 | ||
156 | ColorData::~ColorData() | |
157 | { | |
158 | if (colorData == this) | |
159 | colorData = nullptr; | |
795
195fa1fff9c3
- changed all color usage to use LDColor classes instead of color indices. Added support for direct colors.
Santeri Piippo <crimsondusk64@gmail.com>
parents:
706
diff
changeset
|
160 | } |
946 | 161 | |
998 | 162 | bool ColorData::contains (int code) const |
946 | 163 | { |
998 | 164 | return code >= 0 and code < EntryCount; |
165 | } | |
166 | ||
167 | const ColorData::Entry& ColorData::get (int code) const | |
168 | { | |
169 | if (not contains (code)) | |
170 | throw std::runtime_error ("Attempted to get non-existant color information"); | |
946 | 171 | |
998 | 172 | return m_data[code]; |
173 | } | |
174 | ||
175 | void ColorData::loadFromLdconfig() | |
176 | { | |
177 | if (not g_win) | |
178 | return; | |
179 | ||
180 | QString path = g_win->documents()->findDocumentPath ("LDConfig.ldr", false); | |
181 | QFile fp (path); | |
182 | ||
183 | if (not fp.open (QIODevice::ReadOnly)) | |
946 | 184 | { |
998 | 185 | QMessageBox::critical (nullptr, "Error", "Unable to open LDConfig.ldr for parsing: " + fp.errorString()); |
946 | 186 | return; |
187 | } | |
188 | ||
998 | 189 | // TODO: maybe LDConfig can be loaded as a Document? Or would that be overkill? |
190 | while (not fp.atEnd()) | |
946 | 191 | { |
998 | 192 | QString line = QString::fromUtf8 (fp.readLine()); |
946 | 193 | |
194 | if (line.isEmpty() or line[0] != '0') | |
195 | continue; // empty or illogical | |
196 | ||
197 | line.remove ('\r'); | |
198 | line.remove ('\n'); | |
199 | ||
200 | // Parse the line | |
998 | 201 | LDConfigParser parser (line, ' '); |
202 | QString name; | |
203 | QString facename; | |
204 | QString edgename; | |
205 | QString codestring; | |
946 | 206 | |
207 | // Check 0 !COLOUR, parse the name | |
998 | 208 | if (not parser.compareToken (0, "0") or not parser.compareToken (1, "!COLOUR") or not parser.getToken (name, 2)) |
946 | 209 | continue; |
210 | ||
211 | // Replace underscores in the name with spaces for readability | |
212 | name.replace ("_", " "); | |
213 | ||
998 | 214 | if (not parser.parseTag ("CODE", codestring)) |
946 | 215 | continue; |
216 | ||
217 | bool ok; | |
998 | 218 | int code = codestring.toShort (&ok); |
946 | 219 | |
998 | 220 | if (not ok or not contains (code)) |
946 | 221 | continue; |
222 | ||
998 | 223 | if (not parser.parseTag ("VALUE", facename) or not parser.parseTag ("EDGE", edgename)) |
946 | 224 | continue; |
225 | ||
226 | // Ensure that our colors are correct | |
998 | 227 | QColor faceColor (facename); |
228 | QColor edgeColor (edgename); | |
946 | 229 | |
230 | if (not faceColor.isValid() or not edgeColor.isValid()) | |
231 | continue; | |
232 | ||
998 | 233 | Entry& entry = m_data[code]; |
946 | 234 | entry.name = name; |
235 | entry.faceColor = faceColor; | |
236 | entry.edgeColor = edgeColor; | |
237 | entry.hexcode = facename; | |
998 | 238 | |
239 | if (parser.parseTag ("ALPHA", codestring)) | |
240 | entry.faceColor.setAlpha (qBound (0, codestring.toInt(), 255)); | |
946 | 241 | } |
242 | } | |
243 | ||
244 | // ============================================================================= | |
245 | // | |
246 | LDConfigParser::LDConfigParser (QString inText, char sep) | |
247 | { | |
248 | m_tokens = inText.split (sep, QString::SkipEmptyParts); | |
249 | m_pos = -1; | |
250 | } | |
251 | ||
252 | // ============================================================================= | |
253 | // | |
254 | bool LDConfigParser::getToken (QString& val, const int pos) | |
255 | { | |
256 | if (pos >= m_tokens.size()) | |
257 | return false; | |
258 | ||
259 | val = m_tokens[pos]; | |
260 | return true; | |
261 | } | |
262 | ||
263 | // ============================================================================= | |
264 | // | |
265 | bool LDConfigParser::findToken (int& result, char const* needle, int args) | |
266 | { | |
267 | for (int i = 0; i < (m_tokens.size() - args); ++i) | |
268 | { | |
269 | if (m_tokens[i] == needle) | |
270 | { | |
271 | result = i; | |
272 | return true; | |
273 | } | |
274 | } | |
275 | ||
276 | return false; | |
277 | } | |
278 | ||
279 | // ============================================================================= | |
280 | // | |
281 | bool LDConfigParser::compareToken (int inPos, QString text) | |
282 | { | |
283 | QString tok; | |
284 | ||
285 | if (not getToken (tok, inPos)) | |
286 | return false; | |
287 | ||
288 | return (tok == text); | |
289 | } | |
290 | ||
291 | // ============================================================================= | |
292 | // | |
293 | // Helper function for parseLDConfig | |
294 | // | |
998 | 295 | bool LDConfigParser::parseTag (char const* tag, QString& val) |
946 | 296 | { |
297 | int pos; | |
298 | ||
299 | // Try find the token and get its position | |
300 | if (not findToken (pos, tag, 1)) | |
301 | return false; | |
302 | ||
303 | // Get the token after it and store it into val | |
304 | return getToken (val, pos + 1); | |
305 | } |