https://github.com/tflsguoyu/layeredbsdf
Tip revision: ca6e9b19fb122c126d605207d9f4790e86b03651 authored by Guo Yu on 19 September 2022, 21:16:05 UTC
Update README.md
Update README.md
Tip revision: ca6e9b1
upgrade.cpp
/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2014 by Wenzel Jakob and others.
Mitsuba is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License Version 3
as published by the Free Software Foundation.
Mitsuba 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 "upgrade.h"
#include "save.h"
#include <mitsuba/core/fresolver.h>
#include <boost/algorithm/string.hpp>
#include <QtXmlPatterns/QtXmlPatterns>
struct VersionComparator {
inline bool operator()(const std::pair<Version, fs::path> &s1,
const std::pair<Version, fs::path> &s2) const {
return s1.first < s2.first;
}
};
class XSLTMessageHandler : public QAbstractMessageHandler {
public:
XSLTMessageHandler() : m_fatalError(false) { }
void handleMessage(QtMsgType type, const QString &_descr, const QUrl &id, const QSourceLocation &loc) {
QString descr(_descr);
int paragraphStart = descr.indexOf("<p>");
int paragraphEnd = descr.indexOf("</p>");
if (paragraphStart != -1 && paragraphEnd != -1)
descr = descr.mid(paragraphStart+3, paragraphEnd-paragraphStart-3);
if (loc.isNull())
SLog(EWarn, "%s", qPrintable(descr));
else
SLog(EWarn, "%s (line %i, column %i, url=%s)", qPrintable(descr),
loc.line(), loc.column(), qPrintable(id.toString()));
if (type == QtFatalMsg)
m_fatalError = true;
}
inline bool fatalError() const { return m_fatalError; }
private:
bool m_fatalError;
};
UpgradeManager::UpgradeManager(const FileResolver *resolver) : m_resolver(resolver) {
fs::path transformationPath =
resolver->resolveAbsolute("data/schema/scene.xsd").parent_path();
fs::directory_iterator it(transformationPath), end;
SLog(EInfo, "Searching for transformations..");
for (; it != end; ++it) {
fs::path file = *it;
std::string extension = file.extension().string(),
filename = file.filename().string();
if (boost::to_lower_copy(extension) != ".xsl" ||
!boost::starts_with(filename, "upgrade_"))
continue;
Version version(filename.substr(8, filename.length()-12));
m_transformations.push_back(std::make_pair(version, file));
}
std::sort(m_transformations.begin(), m_transformations.end(), VersionComparator());
for (size_t i=0; i<m_transformations.size(); ++i)
SLog(EInfo, " - registered transformation \"%s\", which updates to version %s",
m_transformations[i].second.filename().string().c_str(),
m_transformations[i].first.toString().c_str());
}
void UpgradeManager::performUpgrade(const QString &filename, const Version &version) {
QString backupFilename = filename;
if (backupFilename.endsWith(".xml", Qt::CaseInsensitive))
backupFilename.replace(backupFilename.length()-4, 4, ".bak");
SLog(EInfo, "Saving a backup copy of \"%s\" as \"%s\"",
QStringToUTF8(filename), QStringToUTF8(backupFilename));
QFile file(filename), backupFile(backupFilename);
if (backupFile.exists())
backupFile.remove();
if (!file.copy(backupFilename))
SLog(EError, "Could not create a backup copy -- "
"stopping the upgrade operation!");
if (!file.open(QIODevice::ReadOnly))
SLog(EError, "Unable to open \"%s\" with read access -- stopping "
"the upgrade operation.", QStringToUTF8(filename));
QByteArray inputArray = file.readAll(), outputArray;
file.close();
QBuffer inputBuffer(&inputArray);
QBuffer outputBuffer(&outputArray);
XSLTMessageHandler handler;
int nTransformations=0;
for (size_t i=0; i<m_transformations.size(); ++i) {
if (m_transformations[i].first <= version)
continue;
inputBuffer.open(QIODevice::ReadOnly);
outputBuffer.open(QIODevice::WriteOnly | QIODevice::Truncate);
SLog(EInfo, "Applying transformation \"%s\" ..",
m_transformations[i].second.filename().string().c_str());
QString trafoFilename = fromFsPath(m_transformations[i].second);
QFile trafoFile(trafoFilename);
if (!trafoFile.open(QIODevice::ReadOnly | QIODevice::Text))
SLog(EError, "Unable to open the stylesheet \"%s\" -- stopping "
"the upgrade operation.", QStringToUTF8(trafoFilename));
QXmlQuery query(QXmlQuery::XSLT20);
query.setMessageHandler(&handler);
query.setFocus(&inputBuffer);
query.setQuery(&trafoFile);
if (!query.isValid())
SLog(EError, "Unable to parse the stylesheet \"%s\" -- stopping "
"the upgrade operation.", QStringToUTF8(trafoFilename));
SLog(EInfo, "Transformation is ready, running it now..");
QXmlFormatter formatter(query, &outputBuffer);
formatter.setIndentationDepth(1);
query.evaluateTo(&formatter);
if (handler.fatalError())
SLog(EError, "A fatal error was encountered -- stopping "
"the upgrade operation.");
/* Swap the outputs */
inputBuffer.close();
outputBuffer.close();
inputArray = outputArray;
++nTransformations;
}
if (nTransformations == 0) {
SLog(EError, "Strange -- no transformations were applied? "
"Stopping the upgrade operation.");
}
/* Done, write back to disk */
SLog(EInfo, "Successfully applied %i transformations, writing the result "
"to \"%s\" ..", nTransformations, QStringToUTF8(filename));
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
SLog(EError, "Unable to open \"%s\" with write access -- stopping "
"the upgrade operation.", QStringToUTF8(filename));
}
int line, column;
QString errorMsg;
QDomDocument doc;
if (!doc.setContent(inputArray, &errorMsg, &line, &column))
SLog(EError, "Unable to parse file: error %s at line %i, colum %i",
QStringToUTF8(errorMsg), line, column);
QDomElement root = doc.documentElement();
/* Search for include nodes */
QDomNode n = root.firstChild();
while (!n.isNull()) {
QDomElement e = n.toElement();
if (!e.isNull()) {
if (e.tagName() == "include") {
fs::path path = m_resolver->resolve(toFsPath(e.attribute("filename")));
SLog(EInfo, "Recursively upgrading include file \"%s\" ..",
path.string().c_str());
performUpgrade(fromFsPath(path), version);
}
}
n = n.nextSibling();
}
QTextStream input(inputArray);
QTextStream output(&file);
output << "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
<< endl << endl;
cleanupXML(input, output);
file.close();
QDomDocument tooltipDoc;
}