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 | } |