src/colors.cpp

changeset 952
f116b63c4844
parent 946
9cbd658b63f9
child 962
a4b463a7ee82
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/colors.cpp	Sat Aug 29 17:07:39 2015 +0300
@@ -0,0 +1,293 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013, 2014 Teemu Piippo
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <QFile>
+#include "main.h"
+#include "colors.h"
+#include "ldDocument.h"
+#include "miscallenous.h"
+#include "mainWindow.h"
+
+struct ColorDataEntry
+{
+	QString name;
+	QString hexcode;
+	QColor faceColor;
+	QColor edgeColor;
+};
+
+static ColorDataEntry ColorData[512];
+
+void InitColors()
+{
+	print ("Initializing color information.\n");
+
+	// Always make sure there's 16 and 24 available. They're special like that.
+	ColorData[MainColor].faceColor =
+	ColorData[MainColor].hexcode = "#AAAAAA";
+	ColorData[MainColor].edgeColor = Qt::black;
+	ColorData[MainColor].name = "Main color";
+
+	ColorData[EdgeColor].faceColor =
+	ColorData[EdgeColor].edgeColor =
+	ColorData[EdgeColor].hexcode = "#000000";
+	ColorData[EdgeColor].name = "Edge color";
+
+	parseLDConfig();
+}
+
+bool LDColor::isValid() const
+{
+	if (isLDConfigColor() and ColorData[index()].name.isEmpty())
+		return false; // Unknown LDConfig color
+
+	return m_index != -1;
+}
+
+bool LDColor::isLDConfigColor() const
+{
+	return index() >= 0 and index() < countof (ColorData);
+}
+
+QString LDColor::name() const
+{
+	if (isDirect())
+		return "0x" + QString::number (index(), 16).toUpper();
+	else if (isLDConfigColor())
+		return ColorData[index()].name;
+	else if (index() == -1)
+		return "null color";
+	else
+		return "";
+}
+
+QString LDColor::hexcode() const
+{
+	return faceColor().name();
+}
+
+QColor LDColor::faceColor() const
+{
+	if (isDirect())
+	{
+		QColor color;
+		color.setRed ((index() & 0x0FF0000) >> 16);
+		color.setGreen ((index() & 0x000FF00) >> 8);
+		color.setBlue (index() & 0x00000FF);
+
+		if (index() >= 0x3000000)
+			color.setAlpha (128);
+
+		return color;
+	}
+	else if (isLDConfigColor())
+	{
+		return ColorData[index()].faceColor;
+	}
+	else
+	{
+		return Qt::black;
+	}
+}
+
+QColor LDColor::edgeColor() const
+{
+	if (isDirect())
+		return Luma (faceColor()) < 48 ? Qt::white : Qt::black;
+	else if (isLDConfigColor())
+		return ColorData[index()].edgeColor;
+	else
+		return Qt::black;
+}
+
+int LDColor::luma() const
+{
+	return Luma (faceColor());
+}
+
+int LDColor::edgeLuma() const
+{
+	return Luma (edgeColor());
+}
+
+qint32 LDColor::index() const
+{
+	return m_index;
+}
+
+QString LDColor::indexString() const
+{
+	if (isDirect())
+		return "0x" + QString::number (index(), 16).toUpper();
+
+	return QString::number (index());
+}
+
+bool LDColor::isDirect() const
+{
+	return index() >= 0x02000000;
+}
+
+int Luma (const QColor& col)
+{
+	return (0.2126f * col.red()) + (0.7152f * col.green()) + (0.0722f * col.blue());
+}
+
+int CountLDConfigColors()
+{
+	return countof (ColorData);
+}
+
+void parseLDConfig()
+{
+	QFile* fp = OpenLDrawFile ("LDConfig.ldr", false);
+
+	if (fp == nullptr)
+	{
+		Critical (QObject::tr ("Unable to open LDConfig.ldr for parsing."));
+		return;
+	}
+
+	// Read in the lines
+	while (not fp->atEnd())
+	{
+		QString line = QString::fromUtf8 (fp->readLine());
+
+		if (line.isEmpty() or line[0] != '0')
+			continue; // empty or illogical
+
+		line.remove ('\r');
+		line.remove ('\n');
+
+		// Parse the line
+		LDConfigParser pars (line, ' ');
+
+		int code = 0, alpha = 255;
+		QString name, facename, edgename, valuestr;
+
+		// Check 0 !COLOUR, parse the name
+		if (not pars.compareToken (0, "0") or
+			not pars.compareToken (1, "!COLOUR") or
+			not pars.getToken (name, 2))
+		{
+			continue;
+		}
+
+		// Replace underscores in the name with spaces for readability
+		name.replace ("_", " ");
+
+		// Get the CODE tag
+		if (not pars.parseLDConfigTag ("CODE", valuestr))
+			continue;
+
+		// Ensure that the code is within [0 - 511]
+		bool ok;
+		code = valuestr.toShort (&ok);
+
+		if (not ok or code < 0 or code >= 512)
+			continue;
+
+		// VALUE and EDGE tags
+		if (not pars.parseLDConfigTag ("VALUE", facename) or not pars.parseLDConfigTag ("EDGE", edgename))
+			continue;
+
+		// Ensure that our colors are correct
+		QColor faceColor (facename),
+			edgeColor (edgename);
+
+		if (not faceColor.isValid() or not edgeColor.isValid())
+			continue;
+
+		// Parse alpha if given.
+		if (pars.parseLDConfigTag ("ALPHA", valuestr))
+			alpha = Clamp (valuestr.toInt(), 0, 255);
+
+		ColorDataEntry& entry = ColorData[code];
+		entry.name = name;
+		entry.faceColor = faceColor;
+		entry.edgeColor = edgeColor;
+		entry.hexcode = facename;
+		entry.faceColor.setAlpha (alpha);
+	}
+
+	fp->close();
+	fp->deleteLater();
+}
+
+// =============================================================================
+//
+LDConfigParser::LDConfigParser (QString inText, char sep)
+{
+	m_tokens = inText.split (sep, QString::SkipEmptyParts);
+	m_pos = -1;
+}
+
+// =============================================================================
+//
+bool LDConfigParser::getToken (QString& val, const int pos)
+{
+	if (pos >= m_tokens.size())
+		return false;
+
+	val = m_tokens[pos];
+	return true;
+}
+
+// =============================================================================
+//
+bool LDConfigParser::findToken (int& result, char const* needle, int args)
+{
+	for (int i = 0; i < (m_tokens.size() - args); ++i)
+	{
+		if (m_tokens[i] == needle)
+		{
+			result = i;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+// =============================================================================
+//
+bool LDConfigParser::compareToken (int inPos, QString text)
+{
+	QString tok;
+
+	if (not getToken (tok, inPos))
+		return false;
+
+	return (tok == text);
+}
+
+// =============================================================================
+//
+// Helper function for parseLDConfig
+//
+bool LDConfigParser::parseLDConfigTag (char const* tag, QString& val)
+{
+	int pos;
+
+	// Try find the token and get its position
+	if (not findToken (pos, tag, 1))
+		return false;
+
+	// Get the token after it and store it into val
+	return getToken (val, pos + 1);
+}
\ No newline at end of file

mercurial