<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "FabricUIManager.h"

#include <glog/logging.h>

#include <fabric/core/LayoutContext.h>
#include <fabric/view/ViewComponentDescriptor.h>
#include <fabric/view/ViewProps.h>
#include <fabric/view/ViewShadowNode.h>

#include "IFabricPlatformUIOperationManager.h"

namespace facebook {
namespace react {

static const RawProps rawPropsFromDynamic(const folly::dynamic object) {
  // TODO: Convert this to something smarter, probably returning `std::iterator`.
  RawProps result;

  if (object.isNull()) {
    return result;
  }

  assert(object.isObject());

  for (const auto &pair : object.items()) {
    assert(pair.first.isString());
    result[pair.first.asString()] = pair.second;
  }

  return result;
}

FabricUIManager::FabricUIManager(const std::shared_ptr<IFabricPlatformUIOperationManager> &platformUIOperationManager):
  platformUIOperationManager_(platformUIOperationManager) {

  SharedComponentDescriptor viewComponentDescriptor = std::make_shared<ViewComponentDescriptor>();
  _registry.registerComponentDescriptor(viewComponentDescriptor);
}

SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int rootTag, folly::dynamic props, void *instanceHandle) {
  LOG(INFO) << "FabricUIManager::createNode(tag: " << tag << ", name: " << viewName << ", rootTag" << rootTag << ", props: " << props << ")";
  ComponentDescriptor &componentDescriptor = *_registry["View"];
  RawProps rawProps = rawPropsFromDynamic(props);
  SharedShadowNode shadowNode = componentDescriptor.createShadowNode(tag, rootTag, instanceHandle, rawProps);
  LOG(INFO) << "FabricUIManager::createNode() -> " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
  return shadowNode;
}

SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode) {
  LOG(INFO) << "FabricUIManager::cloneNode(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
  ComponentDescriptor &componentDescriptor = *_registry[shadowNode];
  SharedShadowNode clonnedShadowNode = componentDescriptor.cloneShadowNode(shadowNode);
  LOG(INFO) << "FabricUIManager::cloneNode() -> " << clonnedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
  return clonnedShadowNode;
}

SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNode &shadowNode) {
  LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
  // Assuming semantic: Cloning with same props but empty children.
  ComponentDescriptor &componentDescriptor = *_registry[shadowNode];
  SharedShadowNode clonnedShadowNode = componentDescriptor.cloneShadowNode(shadowNode, nullptr, {});
  LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren() -> " << clonnedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
  return clonnedShadowNode;
}

SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode &shadowNode, folly::dynamic props) {
  LOG(INFO) << "FabricUIManager::cloneNodeWithNewProps(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", props: " << props << ")";
  // Assuming semantic: Cloning with same children and specified props.
  ComponentDescriptor &componentDescriptor = *_registry[shadowNode];
  RawProps rawProps = rawPropsFromDynamic(props);
  SharedShadowNode clonnedShadowNode = componentDescriptor.cloneShadowNode(shadowNode, std::make_shared<const RawProps>(rawProps), nullptr);
  LOG(INFO) << "FabricUIManager::cloneNodeWithNewProps() -> " << clonnedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
  return clonnedShadowNode;
}

SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedShadowNode &shadowNode, folly::dynamic props) {
  LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildrenAndProps(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", props: " << props << ")";
  // Assuming semantic: Cloning with empty children and specified props.
  ComponentDescriptor &componentDescriptor = *_registry[shadowNode];
  RawProps rawProps = rawPropsFromDynamic(props);
  SharedShadowNode clonnedShadowNode = componentDescriptor.cloneShadowNode(shadowNode, std::make_shared<const RawProps>(rawProps), {});
  LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildrenAndProps() -> " << clonnedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
  return clonnedShadowNode;
}

void FabricUIManager::appendChild(const SharedShadowNode &parentShadowNode, const SharedShadowNode &childShadowNode) {
  LOG(INFO) << "FabricUIManager::appendChild(parentShadowNode: " << parentShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", childShadowNode: " << childShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
  ComponentDescriptor &componentDescriptor = *_registry[parentShadowNode];
  componentDescriptor.appendChild(parentShadowNode, childShadowNode);
}

SharedShadowNodeUnsharedList FabricUIManager::createChildSet(int rootTag) {
  LOG(INFO) << "FabricUIManager::createChildSet(rootTag: " << rootTag << ")";
  return std::make_shared<SharedShadowNodeList>(SharedShadowNodeList({}));
}

void FabricUIManager::appendChildToSet(const SharedShadowNodeUnsharedList &shadowNodeList, const SharedShadowNode &shadowNode) {
  LOG(INFO) << "FabricUIManager::appendChildToSet(shadowNodeList: " << shadowNodeList << ", shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
  shadowNodeList->push_back(shadowNode);
}

void FabricUIManager::completeRoot(int rootTag, const SharedShadowNodeUnsharedList &children) {
  LOG(INFO) << "FabricUIManager::appendChildToSet(rootTag: " << rootTag << ", shadowNodeList: " << children << ")";
  ComponentDescriptor &componentDescriptor = *_registry["View"];
  SharedShadowNode previousRootShadowNode = componentDescriptor.createShadowNode(rootTag, rootTag, nullptr, {});
  auto childrenCopy = std::make_shared<const SharedShadowNodeList>(SharedShadowNodeList(*children));
  SharedShadowNode rootShadowNode = componentDescriptor.cloneShadowNode(previousRootShadowNode, nullptr, childrenCopy);

  SharedViewShadowNode viewShadowNode = std::dynamic_pointer_cast<const ViewShadowNode>(rootShadowNode);
  LayoutContext layoutContext = LayoutContext();
  layoutContext.affectedShadowNodes = std::make_shared<std::unordered_set<SharedLayoutableShadowNode>>();

  LOG(INFO) << "Shadow tree *before* layout: \n" << viewShadowNode->getDebugDescription() ;

  auto nonConstViewShadowNode = std::const_pointer_cast<ViewShadowNode>(viewShadowNode);
  nonConstViewShadowNode->layout(layoutContext);

  rootShadowNode->sealRecursive();

  LOG(INFO) << "Shadow tree *after* layout: \n" << nonConstViewShadowNode->getDebugDescription();
}

} // namespace react
} // namespace facebook
<commit_msg>Fabric: Fixed bug in node management in FabricUIManager<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "FabricUIManager.h"

#include <glog/logging.h>

#include <fabric/core/LayoutContext.h>
#include <fabric/view/ViewComponentDescriptor.h>
#include <fabric/view/ViewProps.h>
#include <fabric/view/ViewShadowNode.h>

#include "IFabricPlatformUIOperationManager.h"

namespace facebook {
namespace react {

static const RawProps rawPropsFromDynamic(const folly::dynamic object) {
  // TODO: Convert this to something smarter, probably returning `std::iterator`.
  RawProps result;

  if (object.isNull()) {
    return result;
  }

  assert(object.isObject());

  for (const auto &pair : object.items()) {
    assert(pair.first.isString());
    result[pair.first.asString()] = pair.second;
  }

  return result;
}

FabricUIManager::FabricUIManager(const std::shared_ptr<IFabricPlatformUIOperationManager> &platformUIOperationManager):
  platformUIOperationManager_(platformUIOperationManager) {

  SharedComponentDescriptor viewComponentDescriptor = std::make_shared<ViewComponentDescriptor>();
  _registry.registerComponentDescriptor(viewComponentDescriptor);
}

SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int rootTag, folly::dynamic props, void *instanceHandle) {
  LOG(INFO) << "FabricUIManager::createNode(tag: " << tag << ", name: " << viewName << ", rootTag" << rootTag << ", props: " << props << ")";
  ComponentDescriptor &componentDescriptor = *_registry["View"];
  RawProps rawProps = rawPropsFromDynamic(props);
  SharedShadowNode shadowNode = componentDescriptor.createShadowNode(tag, rootTag, instanceHandle, rawProps);
  LOG(INFO) << "FabricUIManager::createNode() -> " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
  return shadowNode;
}

SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode) {
  LOG(INFO) << "FabricUIManager::cloneNode(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
  ComponentDescriptor &componentDescriptor = *_registry[shadowNode];
  SharedShadowNode clonnedShadowNode = componentDescriptor.cloneShadowNode(shadowNode);
  LOG(INFO) << "FabricUIManager::cloneNode() -> " << clonnedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
  return clonnedShadowNode;
}

SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNode &shadowNode) {
  LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
  // Assuming semantic: Cloning with same props but empty children.
  ComponentDescriptor &componentDescriptor = *_registry[shadowNode];
  SharedShadowNode clonnedShadowNode = componentDescriptor.cloneShadowNode(shadowNode, nullptr, ShadowNode::emptySharedShadowNodeSharedList());
  LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren() -> " << clonnedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
  return clonnedShadowNode;
}

SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode &shadowNode, folly::dynamic props) {
  LOG(INFO) << "FabricUIManager::cloneNodeWithNewProps(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", props: " << props << ")";
  // Assuming semantic: Cloning with same children and specified props.
  ComponentDescriptor &componentDescriptor = *_registry[shadowNode];
  RawProps rawProps = rawPropsFromDynamic(props);
  SharedShadowNode clonnedShadowNode = componentDescriptor.cloneShadowNode(shadowNode, std::make_shared<const RawProps>(rawProps), nullptr);
  LOG(INFO) << "FabricUIManager::cloneNodeWithNewProps() -> " << clonnedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
  return clonnedShadowNode;
}

SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedShadowNode &shadowNode, folly::dynamic props) {
  LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildrenAndProps(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", props: " << props << ")";
  // Assuming semantic: Cloning with empty children and specified props.
  ComponentDescriptor &componentDescriptor = *_registry[shadowNode];
  RawProps rawProps = rawPropsFromDynamic(props);
  SharedShadowNode clonnedShadowNode = componentDescriptor.cloneShadowNode(shadowNode, std::make_shared<const RawProps>(rawProps), ShadowNode::emptySharedShadowNodeSharedList());
  LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildrenAndProps() -> " << clonnedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
  return clonnedShadowNode;
}

void FabricUIManager::appendChild(const SharedShadowNode &parentShadowNode, const SharedShadowNode &childShadowNode) {
  LOG(INFO) << "FabricUIManager::appendChild(parentShadowNode: " << parentShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", childShadowNode: " << childShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
  ComponentDescriptor &componentDescriptor = *_registry[parentShadowNode];
  componentDescriptor.appendChild(parentShadowNode, childShadowNode);
}

SharedShadowNodeUnsharedList FabricUIManager::createChildSet(int rootTag) {
  LOG(INFO) << "FabricUIManager::createChildSet(rootTag: " << rootTag << ")";
  return std::make_shared<SharedShadowNodeList>(SharedShadowNodeList({}));
}

void FabricUIManager::appendChildToSet(const SharedShadowNodeUnsharedList &shadowNodeList, const SharedShadowNode &shadowNode) {
  LOG(INFO) << "FabricUIManager::appendChildToSet(shadowNodeList: " << shadowNodeList << ", shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
  shadowNodeList->push_back(shadowNode);
}

void FabricUIManager::completeRoot(int rootTag, const SharedShadowNodeUnsharedList &children) {
  LOG(INFO) << "FabricUIManager::appendChildToSet(rootTag: " << rootTag << ", shadowNodeList: " << children << ")";
  ComponentDescriptor &componentDescriptor = *_registry["View"];
  SharedShadowNode previousRootShadowNode = componentDescriptor.createShadowNode(rootTag, rootTag, nullptr, {});
  auto childrenCopy = std::make_shared<const SharedShadowNodeList>(SharedShadowNodeList(*children));
  SharedShadowNode rootShadowNode = componentDescriptor.cloneShadowNode(previousRootShadowNode, nullptr, childrenCopy);

  SharedViewShadowNode viewShadowNode = std::dynamic_pointer_cast<const ViewShadowNode>(rootShadowNode);
  LayoutContext layoutContext = LayoutContext();
  layoutContext.affectedShadowNodes = std::make_shared<std::unordered_set<SharedLayoutableShadowNode>>();

  LOG(INFO) << "Shadow tree *before* layout: \n" << viewShadowNode->getDebugDescription() ;

  auto nonConstViewShadowNode = std::const_pointer_cast<ViewShadowNode>(viewShadowNode);
  nonConstViewShadowNode->layout(layoutContext);

  rootShadowNode->sealRecursive();

  LOG(INFO) << "Shadow tree *after* layout: \n" << nonConstViewShadowNode->getDebugDescription();
}

} // namespace react
} // namespace facebook
<|endoftext|>


<commit_before>/* QuickCross Project
 * License: APACHE-2.0
 * Author: Ben Lau
 * Project Site: https://github.com/benlau/quickcross
 *
 */

#include <QtCore>
#include <QUrlQuery>
#include <QGuiApplication>
#include <QPainter>
#include "qcimageprovider.h"
#include "qcimageloader.h"

class QCImageProviderQueryID {
public:

    QCImageProviderQueryID() {
        scaleToFitDpi = false;
    }

    bool hasModification() const {
        return scaleToFitDpi || tintColor.isValid();
    }

    QString removeSuffix(const QString& input) const {
        QStringList token = input.split(".");

        return token[0];
    }

    void parse(QString id) {
        QUrl inputUrl(id);
        QUrl outputUrl;

        fileName = removeSuffix(inputUrl.path());
        QUrlQuery inputQuery (inputUrl);
        QUrlQuery outputQuery;

        outputUrl.setPath(fileName);

        if (inputQuery.hasQueryItem("scaleToFitDpi")) {
            QVariant v = inputQuery.queryItemValue("scaleToFitDpi");
            scaleToFitDpi = v.toBool();
            v = scaleToFitDpi;
            outputQuery.addQueryItem("scaleToFitDpi", v.toString());
        }

        if (inputQuery.hasQueryItem("tintColor")) {
            QVariant v = inputQuery.queryItemValue("tintColor");
            if (QColor::isValidColor(v.toString())) {
                tintColor = QColor(v.toString());
                outputQuery.addQueryItem("tintColor", inputQuery.queryItemValue("tintColor"));
            }
        }

        outputUrl.setQuery(outputQuery.query());
        cacheKey = outputUrl.toString();
    }

    QString fileName;
    bool scaleToFitDpi;
    QString cacheKey;
    QColor tintColor;
};

/// Copy from QuickAndroid project
static void gray(QImage& dest,QImage& src)
{
    for (int y = 0; y < src.height(); ++y) {
        unsigned int *data = (unsigned int *)src.scanLine(y);
        unsigned int *outData = (unsigned int*)dest.scanLine(y);

        for (int x = 0 ; x < src.width(); x++) {
            int val = qGray(data[x]);
            outData[x] = qRgba(val,val,val,qAlpha(data[x]));
        }
    }

}

/// Copy from QuickAndroid project
static QImage colorize(QImage src, QColor tintColor) {
    if (src.format() != QImage::Format_ARGB32) {
        src = src.convertToFormat(QImage::Format_ARGB32);
    }

    QImage dst = QImage(src.size(), src.format());

    gray(dst,src);

    QPainter painter(&dst);

    QColor pureColor = tintColor;
    pureColor.setAlpha(255);

    painter.setCompositionMode(QPainter::CompositionMode_Screen);
    painter.fillRect(0,0,dst.width(),dst.height(),pureColor);
    painter.end();

    if (tintColor.alpha() != 255) {
        QImage buffer = QImage(src.size(), src.format());
        buffer.fill(QColor("transparent"));
        QPainter bufPainter(&buffer);
        qreal opacity = tintColor.alpha() / 255.0;
        bufPainter.setOpacity(opacity);
        bufPainter.drawImage(0,0,dst);
        bufPainter.end();
        dst = buffer;
    }

    if (src.hasAlphaChannel()) {
        dst.setAlphaChannel(src.alphaChannel());
    }

    dst.setDevicePixelRatio(src.devicePixelRatio());

    return dst;
}

static QImage process(const QCImageProviderQueryID& query, QImage image, qreal devicePixelRatio) {
    QImage output = image;

    if (query.scaleToFitDpi) {

        if (output.devicePixelRatio() != devicePixelRatio) {
            qreal ratio = devicePixelRatio / output.devicePixelRatio();
            output = output.scaled(output.width() * ratio, output.height() * ratio, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
            output.setDevicePixelRatio(devicePixelRatio);
        }

    }

    if (query.tintColor.isValid()) {
        output = colorize(output, query.tintColor);
    }

    return output;
}

/*! \class QCImageProvider
    \inmodule QuickCross

    QCImageProvider is an implementation of QQuickImageProvider class that provides an interface for supporint image data in QML.

    This class offeres following features:

    1. Preload all image at startup via QCImageLoader

    2. Image transformation by query string.

\code

Image {
    // Convert a logo to black color
    source: "image://custom/qt-logo-medium?tintColor=" + escape("#FFFFFF");
}

Image {
    // Scale the image to fit current DPI. It is useful for handling BorderImage
    source: "image://custom/qt-logo-medium?scaleToFitDpi=true"
}

\endcode

Setup:

\code

    QCImageLoader *loader = QCImageLoader::instance();
    loader->load(":/img"); // preload all image from ":/img"
    loader->waitForLoaded();

    QQmlApplicationEngine engine;
    engine.addImageProvider("custom", new QCImageProvider());

\endcode

 */

QCImageProvider::QCImageProvider() : QQuickImageProvider(QQmlImageProviderBase::Image)
{
    m_cache.setMaxCost(1024 * 1024 * 10);

    QGuiApplication* app = qobject_cast<QGuiApplication*>(QGuiApplication::instance());
    devicePixelRatio = app->devicePixelRatio();
}

QImage QCImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
    Q_UNUSED(requestedSize);

    QCImageLoader* loader = QCImageLoader::instance();
    QImage result;

    QCImageProviderQueryID query;
    query.parse(id);

    if (query.hasModification()) {

        mutex.lock();

        if (m_cache.contains(query.cacheKey)) {
            result = *m_cache.object((query.cacheKey));
        } else if (loader->contains(query.fileName)){
            result = process(query,loader->image(query.fileName), devicePixelRatio);
            m_cache.insert(query.cacheKey, new QImage(result), result.bytesPerLine() * result.height());
        }

        mutex.unlock();

    } else if (loader->contains(query.fileName)) {
        result = loader->image(query.fileName);
    }

    if (!result.isNull()) {
        *size = result.size();
    }

    return result;
}

int QCImageProvider::cacheSize() const
{
    return m_cache.maxCost();
}

void QCImageProvider::setCacheSize(int cacheSize)
{
    m_cache.setMaxCost(cacheSize);
}
<commit_msg>Minor updates on QCImageProvider document<commit_after>/* QuickCross Project
 * License: APACHE-2.0
 * Author: Ben Lau
 * Project Site: https://github.com/benlau/quickcross
 *
 */

#include <QtCore>
#include <QUrlQuery>
#include <QGuiApplication>
#include <QPainter>
#include "qcimageprovider.h"
#include "qcimageloader.h"

class QCImageProviderQueryID {
public:

    QCImageProviderQueryID() {
        scaleToFitDpi = false;
    }

    bool hasModification() const {
        return scaleToFitDpi || tintColor.isValid();
    }

    QString removeSuffix(const QString& input) const {
        QStringList token = input.split(".");

        return token[0];
    }

    void parse(QString id) {
        QUrl inputUrl(id);
        QUrl outputUrl;

        fileName = removeSuffix(inputUrl.path());
        QUrlQuery inputQuery (inputUrl);
        QUrlQuery outputQuery;

        outputUrl.setPath(fileName);

        if (inputQuery.hasQueryItem("scaleToFitDpi")) {
            QVariant v = inputQuery.queryItemValue("scaleToFitDpi");
            scaleToFitDpi = v.toBool();
            v = scaleToFitDpi;
            outputQuery.addQueryItem("scaleToFitDpi", v.toString());
        }

        if (inputQuery.hasQueryItem("tintColor")) {
            QVariant v = inputQuery.queryItemValue("tintColor");
            if (QColor::isValidColor(v.toString())) {
                tintColor = QColor(v.toString());
                outputQuery.addQueryItem("tintColor", inputQuery.queryItemValue("tintColor"));
            }
        }

        outputUrl.setQuery(outputQuery.query());
        cacheKey = outputUrl.toString();
    }

    QString fileName;
    bool scaleToFitDpi;
    QString cacheKey;
    QColor tintColor;
};

/// Copy from QuickAndroid project
static void gray(QImage& dest,QImage& src)
{
    for (int y = 0; y < src.height(); ++y) {
        unsigned int *data = (unsigned int *)src.scanLine(y);
        unsigned int *outData = (unsigned int*)dest.scanLine(y);

        for (int x = 0 ; x < src.width(); x++) {
            int val = qGray(data[x]);
            outData[x] = qRgba(val,val,val,qAlpha(data[x]));
        }
    }

}

/// Copy from QuickAndroid project
static QImage colorize(QImage src, QColor tintColor) {
    if (src.format() != QImage::Format_ARGB32) {
        src = src.convertToFormat(QImage::Format_ARGB32);
    }

    QImage dst = QImage(src.size(), src.format());

    gray(dst,src);

    QPainter painter(&dst);

    QColor pureColor = tintColor;
    pureColor.setAlpha(255);

    painter.setCompositionMode(QPainter::CompositionMode_Screen);
    painter.fillRect(0,0,dst.width(),dst.height(),pureColor);
    painter.end();

    if (tintColor.alpha() != 255) {
        QImage buffer = QImage(src.size(), src.format());
        buffer.fill(QColor("transparent"));
        QPainter bufPainter(&buffer);
        qreal opacity = tintColor.alpha() / 255.0;
        bufPainter.setOpacity(opacity);
        bufPainter.drawImage(0,0,dst);
        bufPainter.end();
        dst = buffer;
    }

    if (src.hasAlphaChannel()) {
        dst.setAlphaChannel(src.alphaChannel());
    }

    dst.setDevicePixelRatio(src.devicePixelRatio());

    return dst;
}

static QImage process(const QCImageProviderQueryID& query, QImage image, qreal devicePixelRatio) {
    QImage output = image;

    if (query.scaleToFitDpi) {

        if (output.devicePixelRatio() != devicePixelRatio) {
            qreal ratio = devicePixelRatio / output.devicePixelRatio();
            output = output.scaled(output.width() * ratio, output.height() * ratio, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
            output.setDevicePixelRatio(devicePixelRatio);
        }

    }

    if (query.tintColor.isValid()) {
        output = colorize(output, query.tintColor);
    }

    return output;
}

/*! \class QCImageProvider
    \inmodule QuickCross

    QCImageProvider is an implementation of QQuickImageProvider that provides an interface for supporint image data in QML.

    This class offeres following features:

    1. Preload all image at startup via QCImageLoader

    2. Support @2x , @3x image format

    3. Perform image transformation by query string.

    3.1. tintColor - Alters the colors of the source item by applying an tint color.

    3.2. scaleToFitDpi - Scale up / down the source image to fit current DPI

Example:

\code

Image {
    // Convert a logo to white color
    source: "image://custom/qt-logo-medium?tintColor=" + escape("#FFFFFF");
}

Image {
    // Scale the image to fit current DPI. It is useful for handling BorderImage
    source: "image://custom/qt-logo-medium?scaleToFitDpi=true"
}

\endcode

Setup:

\code

QCImageLoader *loader = QCImageLoader::instance();
loader->load(":/img"); // preload all image from ":/img"
loader->waitForLoaded();

QQmlApplicationEngine engine;
engine.addImageProvider("custom", new QCImageProvider());

\endcode

 */

QCImageProvider::QCImageProvider() : QQuickImageProvider(QQmlImageProviderBase::Image)
{
    m_cache.setMaxCost(1024 * 1024 * 10);

    QGuiApplication* app = qobject_cast<QGuiApplication*>(QGuiApplication::instance());
    devicePixelRatio = app->devicePixelRatio();
}

QImage QCImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
    Q_UNUSED(requestedSize);

    QCImageLoader* loader = QCImageLoader::instance();
    QImage result;

    QCImageProviderQueryID query;
    query.parse(id);

    if (query.hasModification()) {

        mutex.lock();

        if (m_cache.contains(query.cacheKey)) {
            result = *m_cache.object((query.cacheKey));
        } else if (loader->contains(query.fileName)){
            result = process(query,loader->image(query.fileName), devicePixelRatio);
            m_cache.insert(query.cacheKey, new QImage(result), result.bytesPerLine() * result.height());
        }

        mutex.unlock();

    } else if (loader->contains(query.fileName)) {
        result = loader->image(query.fileName);
    }

    if (!result.isNull()) {
        *size = result.size();
    }

    return result;
}

int QCImageProvider::cacheSize() const
{
    return m_cache.maxCost();
}

void QCImageProvider::setCacheSize(int cacheSize)
{
    m_cache.setMaxCost(cacheSize);
}
<|endoftext|>


<commit_before>#include "TestScene.h"
#include "BasicGeometryGenerator.h"

using namespace Core;
using namespace Math;
using namespace Rendering;
using namespace Rendering::Camera;
using namespace Rendering::Light;
using namespace Rendering::Shadow;
using namespace Rendering::Geometry;

RenderSetting TestScene::RegistRenderSetting(Engine& engine)
{
//	engine.GetRenderingSystem().GetPostProcessPipeline().SetUseDoF(true);
	engine.GetRenderingSystem().GetPostProcessPipeline().SetUseSSAO(true);

	return RenderSetting("MainCamera",
		engine.GetDirectX().GetBackBufferRect().Cast<uint>(),
		512, 256, 15.0f
	);
}

void TestScene::OnInitialize(Engine& engine)
{
	Object* mainCamObj = engine.GetObjectManager().Find("MainCamera");
	assert(mainCamObj);
	bool hasMainCam = mainCamObj->HasComponent<MainCamera>();
	assert(hasMainCam); // ????

//	Object sphere = engine.GetObjectManager().Add("Sphere");
//	BasicGeometryGenerator::CreateBox(sphere, engine, Vector3(1.0f, 1.0f, 1.0f), uint(DefaultVertexInputTypeFlag::UV0) | uint(DefaultVertexInputTypeFlag::NORMAL));
//	engine.AddRootObject(sphere);

	Object* box = engine.LoadMesh("./Resources/CornellBox/box.obj"); assert(box);
	engine.AddRootObject(*box);

	Transform& tf = box->FetchTransform();
	tf.SetLocalPosition(Vector3(0.3f, -4.7f, 17.7f));
	tf.UpdateEulerAngle(Vector3(-90.0f, 0.0f, 180.0f));
	tf.SetLocalScale(Vector3(5.0f, 5.0f, 5.0f));

	Object& light = engine.GetObjectManager().Add("PointLight");
	light.FetchTransform().SetLocalPosition(Vector3(0.0f, 2.0f, 16.0f));

	PointLight& pl = light.AddComponent<PointLight>();
	pl.GetBase().SetRadius(30.0f);
	pl.GetBase().SetLumen(100);

	PointLightShadow& pls = light.AddComponent<PointLightShadow>();
	pls.GetBase().SetUnderScanSize( Half(0.0f) );

	engine.AddRootObject(light);
	engine.UpdateWorldMatrix();

	auto v = box->FetchTransform().GetWorldPosition() + Vector3(0, 5, 0);
	engine.GetRenderingSystem().GetMainRenderer().GetGlobalIllumination().SetVXGI_VoxelizeCenterPos(v);
}

void TestScene::OnDestroy(Engine&)
{
}

void TestScene::OnRenderPreview()
{
}

void TestScene::OnUpdate()
{
}

void TestScene::OnRenderPost()
{
}

void TestScene::OnInput()
{
}
<commit_msg>TestScene - DoF 켬<commit_after>#include "TestScene.h"
#include "BasicGeometryGenerator.h"

using namespace Core;
using namespace Math;
using namespace Rendering;
using namespace Rendering::Camera;
using namespace Rendering::Light;
using namespace Rendering::Shadow;
using namespace Rendering::Geometry;

RenderSetting TestScene::RegistRenderSetting(Engine& engine)
{
	engine.GetRenderingSystem().GetPostProcessPipeline().SetUseDoF(true);
	engine.GetRenderingSystem().GetPostProcessPipeline().SetUseSSAO(true);

	return RenderSetting("MainCamera",
		engine.GetDirectX().GetBackBufferRect().Cast<uint>(),
		512, 256, 15.0f
	);
}

void TestScene::OnInitialize(Engine& engine)
{
	Object* mainCamObj = engine.GetObjectManager().Find("MainCamera");
	assert(mainCamObj);
	bool hasMainCam = mainCamObj->HasComponent<MainCamera>();
	assert(hasMainCam); // ????

//	Object sphere = engine.GetObjectManager().Add("Sphere");
//	BasicGeometryGenerator::CreateBox(sphere, engine, Vector3(1.0f, 1.0f, 1.0f), uint(DefaultVertexInputTypeFlag::UV0) | uint(DefaultVertexInputTypeFlag::NORMAL));
//	engine.AddRootObject(sphere);

	Object* box = engine.LoadMesh("./Resources/CornellBox/box.obj"); assert(box);
	engine.AddRootObject(*box);

	Transform& tf = box->FetchTransform();
	tf.SetLocalPosition(Vector3(0.3f, -4.7f, 17.7f));
	tf.UpdateEulerAngle(Vector3(-90.0f, 0.0f, 180.0f));
	tf.SetLocalScale(Vector3(5.0f, 5.0f, 5.0f));

	Object& light = engine.GetObjectManager().Add("PointLight");
	light.FetchTransform().SetLocalPosition(Vector3(0.0f, 2.0f, 16.0f));

	PointLight& pl = light.AddComponent<PointLight>();
	pl.GetBase().SetRadius(30.0f);
	pl.GetBase().SetLumen(100);

	PointLightShadow& pls = light.AddComponent<PointLightShadow>();
	pls.GetBase().SetUnderScanSize( Half(0.0f) );

	engine.AddRootObject(light);
	engine.UpdateWorldMatrix();

	auto v = box->FetchTransform().GetWorldPosition() + Vector3(0, 5, 0);
	engine.GetRenderingSystem().GetMainRenderer().GetGlobalIllumination().SetVXGI_VoxelizeCenterPos(v);
}

void TestScene::OnDestroy(Engine&)
{
}

void TestScene::OnRenderPreview()
{
}

void TestScene::OnUpdate()
{
}

void TestScene::OnRenderPost()
{
}

void TestScene::OnInput()
{
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Shanghai Jiao Tong University.
 *     All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an "AS
 *  IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 *  express or implied.  See the License for the specific language
 *  governing permissions and limitations under the License.
 *
 * For more about this software visit:
 *
 *      http://ipads.se.sjtu.edu.cn/projects/wukong
 *
 */

#include <string>
#include <fstream>
#include <iostream>
#include <stdio.h>
#include <dirent.h>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <algorithm>
#include <assert.h>

#include <sys/stat.h>
#include <sys/types.h>

/**
 * transfer str-format RDF data into id-format RDF data (triple rows)
 *
 * A simple manual
 *  $g++ -std=c++11 generate_data.cpp -o generate_data
 *  $./generate_data lubm_raw_40 id_lubm_40
 */

using namespace std;

/* logical we split id-mapping table to normal-vertex and index-vertex table,
   but mapping all strings into the same id space. We reserve 2^NBITS_IDX ids
   for index vertices. */
enum { NBITS_IDX = 17 };

int find_type (string str) {
    if (str.find("^^xsd:int") != string::npos
            || str.find("^^<http://www.w3.org/2001/XMLSchema#int>") != string::npos)
        return 1;
    else if (str.find("^^xsd:float") != string::npos
             || str.find("^^<http://www.w3.org/2001/XMLSchema#float>") != string::npos)
        return 2;
    else if (str.find("^^xsd:double") != string::npos
             || str.find("^^<http://www.w3.org/2001/XMLSchema#double>") != string::npos)
        return 3;
    else
        return 0;
}

string find_value(string str) {
    size_t begin, end;
    begin = str.find('"');
    if (begin == string::npos) {
        cout << "ERROR Format " << endl;
        return "";
    }
    end = str.find('"', begin + 1);

    if (end == string::npos) {
        cout << "ERROR Format " << endl;
        return "";
    }
    return str.substr(begin + 1, end - begin - 1);
}

int
main(int argc, char** argv)
{
    unordered_map<string, int64_t> str_to_id;
    vector<string> normal_str;  // normal-vertex id table (vid)
    vector<string> index_str;   // index-vertex (i.e, predicate or type) id  table (p/tid)
    vector<string> attr_index_str; // index-vertex (i.e attr predicate)
    unordered_map<string, int> index_to_type; //store the attr_index type mapping

    if (argc != 3) {
        printf("usage: ./generate_data src_dir dst_dir\n");
        return -1;
    }

    char *sdir_name = argv[1];
    char *ddir_name = argv[2];

    // create destination directory
    if (mkdir(ddir_name, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) {
        cout << "Error: Creating dst_dir (" << ddir_name << ") failed." << endl;
        exit(-1);
    }

    // open source directory
    DIR *sdir = opendir(sdir_name);
    if (!sdir) {
        cout << "Error: Opening src_dir (" << sdir_name << ") failed." << endl;
        exit(-1);
    }

    // reserve t/pid[0] to predicate-index
    str_to_id["__PREDICATE__"] = 0;
    index_str.push_back("__PREDICATE__");

    // reserve t/pid[1] to type-index
    str_to_id["<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>"] = 1;
    index_str.push_back("<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>");

    // reserve the first two ids for the class of index vertex (i.e, predicate and type)
    int64_t next_index_id = 2;
    int64_t next_normal_id = 1 << NBITS_IDX; // reserve 2^NBITS_IDX ids for index vertices
    int count = 0;

    struct dirent *dent;
    while ((dent = readdir(sdir)) != NULL) {
        if (dent->d_name[0] == '.')
            continue;

        ifstream ifile((string(sdir_name) + "/" + string(dent->d_name)).c_str());
        ofstream ofile((string(ddir_name) + "/id_" + string(dent->d_name)).c_str());
        ofstream attr_file((string(ddir_name) + "/attr_" + string(dent->d_name)).c_str());
        cout << "Process No." << ++count << " input file: " << dent->d_name << "." << endl;

        // str-format: subject predicate object .
        string subject, predicate, object, dot;
        // read (str-format) input file
        while (ifile >> subject >> predicate >> object >> dot) {
            int type = 0;
            // the attr triple
            if ((type = find_type(object)) != 0) {
                if (str_to_id.find(subject) == str_to_id.end()) {
                    str_to_id[subject] = next_normal_id;
                    next_normal_id ++;
                    normal_str.push_back(subject);
                }
                if (str_to_id.find(predicate) == str_to_id.end()) {
                    str_to_id[predicate] = next_index_id;
                    next_index_id ++;
                    attr_index_str.push_back(predicate);
                    index_to_type [predicate] = type;
                }
                string obj = find_value(object);

                attr_file << str_to_id[subject] << "\t"
                          << str_to_id[predicate] << "\t"
                          << type << "\t" << obj << endl;

                //the normal triple
            } else {
                // add a new normal vertex (i.e., vid)
                if (str_to_id.find(subject) == str_to_id.end()) {
                    str_to_id[subject] = next_normal_id;
                    next_normal_id ++;
                    normal_str.push_back(subject);
                }
                // add a new (predicate) index vertex (i.e., pid)
                if (str_to_id.find(predicate) == str_to_id.end()) {
                    str_to_id[predicate] = next_index_id;
                    next_index_id ++;
                    index_str.push_back(predicate);
                }

                // treat different types as individual indexes
                if (predicate == "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>") {
                    // add a new (type) index vertex (i.e., tidx)
                    if (str_to_id.find(object) == str_to_id.end()) {
                        str_to_id[object] = next_index_id;
                        next_index_id ++;
                        index_str.push_back(object);
                    }
                } else {
                    // add a new normal vertex (i.e., vid)
                    if (str_to_id.find(object) == str_to_id.end()) {
                        str_to_id[object] = next_normal_id;
                        next_normal_id ++;
                        normal_str.push_back(object);
                    }
                }

                // write (id-format) output file
                int64_t triple[3];
                triple[0] = str_to_id[subject];
                triple[1] = str_to_id[predicate];
                triple[2] = str_to_id[object];
                ofile << triple[0] << "\t" << triple[1] << "\t" << triple[2] << endl;
            }
        }
    }
    closedir(sdir);

    /* build ID-mapping (str2id) table file for normal vertices */
    {
        ofstream f_normal((string(ddir_name) + "/str_normal").c_str());
        for (int64_t i = 0; i < normal_str.size(); i++)
            f_normal << normal_str[i] << "\t" << str_to_id[normal_str[i]] << endl;
    }

    /* build ID-mapping (str2id) table file for index vertices */
    {
        ofstream f_index((string(ddir_name) + "/str_index").c_str());
        for (int64_t i = 0; i < index_str.size(); i++)
            f_index << index_str[i] << "\t" << str_to_id[index_str[i]] << endl;
    }

    /* build ID-mapping (str2id) table file for attr vertices */
    {
        ofstream f_attr((string(ddir_name) + "/str_attr_index").c_str());
        for (int64_t i = 0; i < attr_index_str.size(); i++)
            f_attr << attr_index_str[i] << "\t"
                   << str_to_id[attr_index_str[i]] << "\t"
                   << index_to_type[attr_index_str[i]] << endl;
    }

    cout << "#total_vertex = " << str_to_id.size() << endl;
    cout << "#normal_vertex = " << normal_str.size() << endl;
    cout << "#index_vertex = " << index_str.size() << endl;
    cout << "#attr_vertex = " << attr_index_str.size() << endl;

    return 0;
}
<commit_msg>generate_data with prefix replacement from yyy<commit_after>/*
 * Copyright (c) 2016 Shanghai Jiao Tong University.
 *     All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an "AS
 *  IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 *  express or implied.  See the License for the specific language
 *  governing permissions and limitations under the License.
 *
 * For more about this software visit:
 *
 *      http://ipads.se.sjtu.edu.cn/projects/wukong
 *
 */

#include <string>
#include <fstream>
#include <iostream>
#include <stdio.h>
#include <dirent.h>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <algorithm>
#include <assert.h>

#include <sys/stat.h>
#include <sys/types.h>

/**
 * transfer str-format RDF data into id-format RDF data (triple rows)
 *
 * A simple manual
 *  $g++ -std=c++11 generate_data.cpp -o generate_data
 *  $./generate_data lubm_raw_40 id_lubm_40
 */

using namespace std;

/* logical we split id-mapping table to normal-vertex and index-vertex table,
   but mapping all strings into the same id space. We reserve 2^NBITS_IDX ids
   for index vertices. */
enum { NBITS_IDX = 17 };

int find_type (string str) {
    if (str.find("^^xsd:int") != string::npos
            || str.find("^^<http://www.w3.org/2001/XMLSchema#int>") != string::npos)
        return 1;
    else if (str.find("^^xsd:float") != string::npos
             || str.find("^^<http://www.w3.org/2001/XMLSchema#float>") != string::npos)
        return 2;
    else if (str.find("^^xsd:double") != string::npos
             || str.find("^^<http://www.w3.org/2001/XMLSchema#double>") != string::npos)
        return 3;
    else
        return 0;
}

string find_value(string str) {
    size_t begin, end;
    begin = str.find('"');
    if (begin == string::npos) {
        cout << "ERROR Format " << endl;
        return "";
    }
    end = str.find('"', begin + 1);

    if (end == string::npos) {
        cout << "ERROR Format " << endl;
        return "";
    }
    return str.substr(begin + 1, end - begin - 1);
}

int
main(int argc, char** argv)
{
    unordered_map<string, int64_t> str_to_id;
    vector<string> normal_str;  // normal-vertex id table (vid)
    vector<string> index_str;   // index-vertex (i.e, predicate or type) id  table (p/tid)
    vector<string> attr_index_str; // index-vertex (i.e attr predicate)
    unordered_map<string, int> index_to_type; //store the attr_index type mapping

    if (argc != 3) {
        printf("usage: ./generate_data src_dir dst_dir\n");
        return -1;
    }

    char *sdir_name = argv[1];
    char *ddir_name = argv[2];

    // create destination directory
    if (mkdir(ddir_name, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) {
        cout << "Error: Creating dst_dir (" << ddir_name << ") failed." << endl;
        exit(-1);
    }

    // open source directory
    DIR *sdir = opendir(sdir_name);
    if (!sdir) {
        cout << "Error: Opening src_dir (" << sdir_name << ") failed." << endl;
        exit(-1);
    }

    // reserve t/pid[0] to predicate-index
    str_to_id["__PREDICATE__"] = 0;
    index_str.push_back("__PREDICATE__");

    // reserve t/pid[1] to type-index
    str_to_id["<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>"] = 1;
    index_str.push_back("<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>");

    // reserve the first two ids for the class of index vertex (i.e, predicate and type)
    int64_t next_index_id = 2;
    int64_t next_normal_id = 1 << NBITS_IDX; // reserve 2^NBITS_IDX ids for index vertices
    int count = 0;

    struct dirent *dent;
    while ((dent = readdir(sdir)) != NULL) {
        if (dent->d_name[0] == '.')
            continue;

        ifstream ifile((string(sdir_name) + "/" + string(dent->d_name)).c_str());
        ofstream ofile((string(ddir_name) + "/id_" + string(dent->d_name)).c_str());
        ofstream attr_file((string(ddir_name) + "/attr_" + string(dent->d_name)).c_str());
        cout << "Process No." << ++count << " input file: " << dent->d_name << "." << endl;

        // prefix mapping
        unordered_map<string, string> str_to_str;

        // str-format: subject predicate object .
        string subject, predicate, object, dot;
        // read (str-format) input file
        while (ifile >> subject >> predicate >> object >> dot) {
            // handle prefix
            if (subject == "@prefix") {
                size_t sindex = predicate.find(':');
                string prekey = predicate.substr(0, sindex);
                str_to_str[prekey] = object;
                continue;
            }

            int type = 0;
            // the attr triple
            if ((type = find_type(object)) != 0) {
                if (str_to_id.find(subject) == str_to_id.end()) {
                    str_to_id[subject] = next_normal_id;
                    next_normal_id ++;
                    normal_str.push_back(subject);
                }
                if (str_to_id.find(predicate) == str_to_id.end()) {
                    str_to_id[predicate] = next_index_id;
                    next_index_id ++;
                    attr_index_str.push_back(predicate);
                    index_to_type [predicate] = type;
                }
                string obj = find_value(object);

                attr_file << str_to_id[subject] << "\t"
                          << str_to_id[predicate] << "\t"
                          << type << "\t" << obj << endl;

                //the normal triple
            } else {
                // replace prefix
                if (str_to_str.size() != 0) {
                    size_t pindex;
                    if ((pindex = subject.find(':')) != string::npos) {
                        string prekey = subject.substr(0, pindex);
                        string lefts = subject.substr(pindex+1, subject.size()-pindex-1);
                        string prev = str_to_str[prekey];
                        subject = prev.substr(0, prev.size()-1) + lefts + '>';
                    }
                    if ((pindex = predicate.find(':')) != string::npos) {
                        string prekey = predicate.substr(0, pindex);
                        string lefts = predicate.substr(pindex+1, predicate.size()-pindex-1);
                        string prev = str_to_str[prekey];
                        predicate = prev.substr(0, prev.size()-1) + lefts + '>';
                    }
                    if ((pindex = object.find(':')) != string::npos) {
                        string prekey = object.substr(0, pindex);
                        string lefts = object.substr(pindex+1, object.size()-pindex-1);
                        string prev = str_to_str[prekey];
                        object = prev.substr(0, prev.size()-1) + lefts + '>';
                    }
                }

                // add a new normal vertex (i.e., vid)
                if (str_to_id.find(subject) == str_to_id.end()) {
                    str_to_id[subject] = next_normal_id;
                    next_normal_id ++;
                    normal_str.push_back(subject);
                }
                // add a new (predicate) index vertex (i.e., pid)
                if (str_to_id.find(predicate) == str_to_id.end()) {
                    str_to_id[predicate] = next_index_id;
                    next_index_id ++;
                    index_str.push_back(predicate);
                }

                // treat different types as individual indexes
                if (predicate == "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>") {
                    // add a new (type) index vertex (i.e., tidx)
                    if (str_to_id.find(object) == str_to_id.end()) {
                        str_to_id[object] = next_index_id;
                        next_index_id ++;
                        index_str.push_back(object);
                    }
                } else {
                    // add a new normal vertex (i.e., vid)
                    if (str_to_id.find(object) == str_to_id.end()) {
                        str_to_id[object] = next_normal_id;
                        next_normal_id ++;
                        normal_str.push_back(object);
                    }
                }

                // write (id-format) output file
                int64_t triple[3];
                triple[0] = str_to_id[subject];
                triple[1] = str_to_id[predicate];
                triple[2] = str_to_id[object];
                ofile << triple[0] << "\t" << triple[1] << "\t" << triple[2] << endl;
            }
        }
    }
    closedir(sdir);

    /* build ID-mapping (str2id) table file for normal vertices */
    {
        ofstream f_normal((string(ddir_name) + "/str_normal").c_str());
        for (int64_t i = 0; i < normal_str.size(); i++)
            f_normal << normal_str[i] << "\t" << str_to_id[normal_str[i]] << endl;
    }

    /* build ID-mapping (str2id) table file for index vertices */
    {
        ofstream f_index((string(ddir_name) + "/str_index").c_str());
        for (int64_t i = 0; i < index_str.size(); i++)
            f_index << index_str[i] << "\t" << str_to_id[index_str[i]] << endl;
    }

    /* build ID-mapping (str2id) table file for attr vertices */
    {
        ofstream f_attr((string(ddir_name) + "/str_attr_index").c_str());
        for (int64_t i = 0; i < attr_index_str.size(); i++)
            f_attr << attr_index_str[i] << "\t"
                   << str_to_id[attr_index_str[i]] << "\t"
                   << index_to_type[attr_index_str[i]] << endl;
    }

    cout << "#total_vertex = " << str_to_id.size() << endl;
    cout << "#normal_vertex = " << normal_str.size() << endl;
    cout << "#index_vertex = " << index_str.size() << endl;
    cout << "#attr_vertex = " << attr_index_str.size() << endl;

    return 0;
}
<|endoftext|>


<commit_before>// conv.cpp
//
#include "common/common.h"
#include "utils/conv.h"
#include "utils/encoding_utf.hpp"

namespace sdl { namespace db { namespace {

template <class string_type>
string_type nchar_to_string(vector_mem_range_t const & data)
{
    static_assert(sizeof(nchar_t) == 2, "");
    const size_t len = mem_size(data);
    if (len && !is_odd(len)) {
        const std::vector<char> src = make_vector(data);
        SDL_ASSERT(src.size() == len);
        using CharIn = uint16;
        static_assert(sizeof(nchar_t) == sizeof(CharIn), "");
        const CharIn * const begin = reinterpret_cast<const CharIn *>(src.data());
        const CharIn * const end = begin + (src.size() / sizeof(CharIn));
        return sdl::locale::conv::utf_to_utf<string_type::value_type, CharIn>(begin, end);
    }
    SDL_ASSERT(!len);
    return{};
}

} // namespace

std::wstring conv::cp1251_to_wide(std::string const & s)
{
    std::wstring w(s.size(), L'\0');
    if (std::mbstowcs(&w[0], s.c_str(), w.size()) == s.size()) {
        return w;
    }
    SDL_ASSERT(!"cp1251_to_wide");
    return{};
}

std::string conv::cp1251_to_utf8(std::string const & s)
{
    A_STATIC_ASSERT_TYPE(char, std::string::value_type);
    std::wstring w(s.size(), L'\0');
    if (std::mbstowcs(&w[0], s.c_str(), w.size()) == s.size()) {
        return sdl::locale::conv::utf_to_utf<std::string::value_type>(w);
    }
    SDL_ASSERT(!"cp1251_to_utf8");
    return {};
}

std::wstring conv::utf8_to_wide(std::string const & s)
{
    A_STATIC_ASSERT_TYPE(wchar_t, std::wstring::value_type); // sizeof(wchar_t) can be 2 or 4 bytes
    return sdl::locale::conv::utf_to_utf<std::wstring::value_type>(s);
}

std::string conv::wide_to_utf8(std::wstring const & s)
{
    return sdl::locale::conv::utf_to_utf<std::string::value_type>(s);
}

std::string conv::nchar_to_utf8(vector_mem_range_t const & data)
{
    return nchar_to_string<std::string>(data);
}

std::wstring conv::nchar_to_wide(vector_mem_range_t const & data)
{
    return nchar_to_string<std::wstring>(data);
}

} // db
} // sdl

#if SDL_DEBUG
namespace sdl { namespace db { namespace {
    class unit_test {
    public:
        unit_test() {
            SDL_ASSERT(!conv::cp1251_to_utf8("cp1251_to_utf8").empty());
            SDL_ASSERT(conv::cp1251_to_utf8("").empty());
        }
    };
    static unit_test s_test;
}}} // sdl::db
#endif //#if SV_DEBUG
<commit_msg>fixed nchar_to_string<commit_after>// conv.cpp
//
#include "common/common.h"
#include "utils/conv.h"
#include "utils/encoding_utf.hpp"

namespace sdl { namespace db { namespace {

template <class string_type>
string_type nchar_to_string(vector_mem_range_t const & data)
{
    static_assert(sizeof(nchar_t) == 2, "");
    const size_t len = mem_size(data);
    if (len && !is_odd(len)) {
        const std::vector<char> src = make_vector(data);
        SDL_ASSERT(src.size() == len);
        using CharIn = uint16;
        static_assert(sizeof(nchar_t) == sizeof(CharIn), "");
        const CharIn * const begin = reinterpret_cast<const CharIn *>(src.data());
        const CharIn * const end = begin + (src.size() / sizeof(CharIn));
        return sdl::locale::conv::utf_to_utf<typename string_type::value_type, CharIn>(begin, end);
    }
    SDL_ASSERT(!len);
    return{};
}

} // namespace

std::wstring conv::cp1251_to_wide(std::string const & s)
{
    std::wstring w(s.size(), L'\0');
    if (std::mbstowcs(&w[0], s.c_str(), w.size()) == s.size()) {
        return w;
    }
    SDL_ASSERT(!"cp1251_to_wide");
    return{};
}

std::string conv::cp1251_to_utf8(std::string const & s)
{
    A_STATIC_ASSERT_TYPE(char, std::string::value_type);
    std::wstring w(s.size(), L'\0');
    if (std::mbstowcs(&w[0], s.c_str(), w.size()) == s.size()) {
        return sdl::locale::conv::utf_to_utf<std::string::value_type>(w);
    }
    SDL_ASSERT(!"cp1251_to_utf8");
    return {};
}

std::wstring conv::utf8_to_wide(std::string const & s)
{
    A_STATIC_ASSERT_TYPE(wchar_t, std::wstring::value_type); // sizeof(wchar_t) can be 2 or 4 bytes
    return sdl::locale::conv::utf_to_utf<std::wstring::value_type>(s);
}

std::string conv::wide_to_utf8(std::wstring const & s)
{
    return sdl::locale::conv::utf_to_utf<std::string::value_type>(s);
}

std::string conv::nchar_to_utf8(vector_mem_range_t const & data)
{
    return nchar_to_string<std::string>(data);
}

std::wstring conv::nchar_to_wide(vector_mem_range_t const & data)
{
    return nchar_to_string<std::wstring>(data);
}

} // db
} // sdl

#if SDL_DEBUG
namespace sdl { namespace db { namespace {
    class unit_test {
    public:
        unit_test() {
            SDL_ASSERT(!conv::cp1251_to_utf8("cp1251_to_utf8").empty());
            SDL_ASSERT(conv::cp1251_to_utf8("").empty());
        }
    };
    static unit_test s_test;
}}} // sdl::db
#endif //#if SV_DEBUG
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

#include <boost/python.hpp>
#include <mapnik/point_symbolizer.hpp>

void export_point_symbolizer()
{
    using namespace boost::python;
    using mapnik::point_symbolizer;

    class_<point_symbolizer>("PointSymbolizer",
                             init<>("Default Point Symbolizer - 4x4 black square"))
        .def (init<std::string const&,
              std::string const&,unsigned,unsigned>("TODO"))
        ;

}
<commit_msg>reflect 'allow_overlap' property in Python bindings (patch from rcoup)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

#include <boost/python.hpp>
#include <mapnik/point_symbolizer.hpp>

void export_point_symbolizer()
{
    using namespace boost::python;
    using mapnik::point_symbolizer;

    class_<point_symbolizer>("PointSymbolizer",
                             init<>("Default Point Symbolizer - 4x4 black square"))
        .def (init<std::string const&,
              std::string const&,unsigned,unsigned>("TODO"))
        .add_property("allow_overlap",
              &point_symbolizer::get_allow_overlap,
              &point_symbolizer::set_allow_overlap)
        ;
}
<|endoftext|>


<commit_before>#ifndef AMGCL_SOLVERS_CG_HPP
#define AMGCL_SOLVERS_CG_HPP

/*
The MIT License

Copyright (c) 2012-2017 Denis Demidov <dennis.demidov@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * \file   amgcl/solver/cg.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Conjugate Gradient method.
 */

#include <boost/tuple/tuple.hpp>
#include <amgcl/backend/interface.hpp>
#include <amgcl/solver/detail/default_inner_product.hpp>
#include <amgcl/util.hpp>

namespace amgcl {

/// Iterative solvers
namespace solver {

/**
 * \defgroup solvers
 * \brief Iterative solvers
 *
 * AMGCL provides several iterative solvers, but it should be easy to use it as
 * a preconditioner with a user-provided solver.  Each solver in AMGCL is a
 * class template. Its single template parameter specifies the backend to use.
 * This allows to preallocate necessary resources at class construction.
 * Obviously, the solver backend has to coincide with the AMG backend.
 */

/** Conjugate Gradients method.
 * \rst
 * An effective method for symmetric positive definite systems [Barr94]_.
 * \endrst
 */
template <
    class Backend,
    class InnerProduct = detail::default_inner_product
    >
class cg {
    public:
        typedef Backend backend_type;

        typedef typename Backend::vector     vector;
        typedef typename Backend::value_type value_type;
        typedef typename Backend::params     backend_params;

        typedef typename math::scalar_of<value_type>::type scalar_type;

        typedef typename math::inner_product_impl<
            typename math::rhs_of<value_type>::type
            >::return_type coef_type;

        /// Solver parameters.
        struct params {
            /// Maximum number of iterations.
            size_t maxiter;

            /// Target relative residual error.
            scalar_type tol;

            /// Target absolute residual error.
            scalar_type abstol;

            params()
                : maxiter(100), tol(1e-8),
                  abstol(std::numeric_limits<scalar_type>::min())
            {}

            params(const boost::property_tree::ptree &p)
                : AMGCL_PARAMS_IMPORT_VALUE(p, maxiter),
                  AMGCL_PARAMS_IMPORT_VALUE(p, tol),
                  AMGCL_PARAMS_IMPORT_VALUE(p, abstol)
            {
                AMGCL_PARAMS_CHECK(p, (maxiter)(tol)(abstol));
            }

            void get(boost::property_tree::ptree &p, const std::string &path) const {
                AMGCL_PARAMS_EXPORT_VALUE(p, path, maxiter);
                AMGCL_PARAMS_EXPORT_VALUE(p, path, tol);
                AMGCL_PARAMS_EXPORT_VALUE(p, path, abstol);
            }
        };

        /// Preallocates necessary data structures for the system of size \p n.
        cg(
                size_t n,
                const params &prm = params(),
                const backend_params &backend_prm = backend_params(),
                const InnerProduct &inner_product = InnerProduct()
          ) : prm(prm), n(n),
              r(Backend::create_vector(n, backend_prm)),
              s(Backend::create_vector(n, backend_prm)),
              p(Backend::create_vector(n, backend_prm)),
              q(Backend::create_vector(n, backend_prm)),
              inner_product(inner_product)
        { }

        /* Computes the solution for the given system matrix \p A and the
         * right-hand side \p rhs.  Returns the number of iterations made and
         * the achieved residual as a ``boost::tuple``. The solution vector
         * \p x provides initial approximation in input and holds the computed
         * solution on output.
         *
         * The system matrix may differ from the matrix used during
         * initialization. This may be used for the solution of non-stationary
         * problems with slowly changing coefficients. There is a strong chance
         * that a preconditioner built for a time step will act as a reasonably
         * good preconditioner for several subsequent time steps [DeSh12]_.
         */
        template <class Matrix, class Precond, class Vec1, class Vec2>
        boost::tuple<size_t, scalar_type> operator()(
                Matrix  const &A,
                Precond const &P,
                Vec1    const &rhs,
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
                Vec2          &x
#else
                Vec2          &&x
#endif
                ) const
        {
            static const coef_type one  = math::identity<coef_type>();
            static const coef_type zero = math::zero<coef_type>();

            backend::residual(rhs, A, x, *r);
            scalar_type norm_rhs = norm(rhs);
            if (norm_rhs < amgcl::detail::eps<scalar_type>(n)) {
                backend::clear(x);
                return boost::make_tuple(0, norm_rhs);
            }

            scalar_type eps  = std::max(prm.tol * norm_rhs, prm.abstol);

            coef_type rho1 = 2 * eps * one;
            coef_type rho2 = zero;
            scalar_type res_norm = norm(*r);

            size_t iter = 0;
            for(; iter < prm.maxiter && math::norm(res_norm) > eps; ++iter) {
                P.apply(*r, *s);

                rho2 = rho1;
                rho1 = inner_product(*r, *s);

                if (iter)
                    backend::axpby(one, *s, rho1 / rho2, *p);
                else
                    backend::copy(*s, *p);

                backend::spmv(one, A, *p, zero, *q);

                coef_type alpha = rho1 / inner_product(*q, *p);

                backend::axpby( alpha, *p, one,  x);
                backend::axpby(-alpha, *q, one, *r);

                res_norm = norm(*r);
            }

            backend::residual(rhs, A, x, *r);
            res_norm = norm(*r);

            return boost::make_tuple(iter, res_norm / norm_rhs);
        }

        /* Computes the solution for the given right-hand side \p rhs. The
         * system matrix is the same that was used for the setup of the
         * preconditioner \p P.  Returns the number of iterations made and the
         * achieved residual as a ``boost::tuple``. The solution vector \p x
         * provides initial approximation in input and holds the computed
         * solution on output.
         */
        template <class Precond, class Vec1, class Vec2>
        boost::tuple<size_t, scalar_type> operator()(
                Precond const &P,
                Vec1    const &rhs,
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
                Vec2          &x
#else
                Vec2          &&x
#endif
                ) const
        {
            return (*this)(P.system_matrix(), P, rhs, x);
        }

        friend std::ostream& operator<<(std::ostream &os, const cg &s) {
            return os << "cg: " << s.n << " unknowns";
        }
    public:
        params prm;

    private:
        size_t n;

        boost::shared_ptr<vector> r;
        boost::shared_ptr<vector> s;
        boost::shared_ptr<vector> p;
        boost::shared_ptr<vector> q;

        InnerProduct inner_product;

        template <class Vec>
        scalar_type norm(const Vec &x) const {
            return sqrt(math::norm(inner_product(x, x)));
        }
};

} // namespace solver
} // namespace amgcl

#endif
<commit_msg>Do not recompute residual on exit from CG<commit_after>#ifndef AMGCL_SOLVERS_CG_HPP
#define AMGCL_SOLVERS_CG_HPP

/*
The MIT License

Copyright (c) 2012-2017 Denis Demidov <dennis.demidov@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * \file   amgcl/solver/cg.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Conjugate Gradient method.
 */

#include <boost/tuple/tuple.hpp>
#include <amgcl/backend/interface.hpp>
#include <amgcl/solver/detail/default_inner_product.hpp>
#include <amgcl/util.hpp>

namespace amgcl {

/// Iterative solvers
namespace solver {

/**
 * \defgroup solvers
 * \brief Iterative solvers
 *
 * AMGCL provides several iterative solvers, but it should be easy to use it as
 * a preconditioner with a user-provided solver.  Each solver in AMGCL is a
 * class template. Its single template parameter specifies the backend to use.
 * This allows to preallocate necessary resources at class construction.
 * Obviously, the solver backend has to coincide with the AMG backend.
 */

/** Conjugate Gradients method.
 * \rst
 * An effective method for symmetric positive definite systems [Barr94]_.
 * \endrst
 */
template <
    class Backend,
    class InnerProduct = detail::default_inner_product
    >
class cg {
    public:
        typedef Backend backend_type;

        typedef typename Backend::vector     vector;
        typedef typename Backend::value_type value_type;
        typedef typename Backend::params     backend_params;

        typedef typename math::scalar_of<value_type>::type scalar_type;

        typedef typename math::inner_product_impl<
            typename math::rhs_of<value_type>::type
            >::return_type coef_type;

        /// Solver parameters.
        struct params {
            /// Maximum number of iterations.
            size_t maxiter;

            /// Target relative residual error.
            scalar_type tol;

            /// Target absolute residual error.
            scalar_type abstol;

            params()
                : maxiter(100), tol(1e-8),
                  abstol(std::numeric_limits<scalar_type>::min())
            {}

            params(const boost::property_tree::ptree &p)
                : AMGCL_PARAMS_IMPORT_VALUE(p, maxiter),
                  AMGCL_PARAMS_IMPORT_VALUE(p, tol),
                  AMGCL_PARAMS_IMPORT_VALUE(p, abstol)
            {
                AMGCL_PARAMS_CHECK(p, (maxiter)(tol)(abstol));
            }

            void get(boost::property_tree::ptree &p, const std::string &path) const {
                AMGCL_PARAMS_EXPORT_VALUE(p, path, maxiter);
                AMGCL_PARAMS_EXPORT_VALUE(p, path, tol);
                AMGCL_PARAMS_EXPORT_VALUE(p, path, abstol);
            }
        };

        /// Preallocates necessary data structures for the system of size \p n.
        cg(
                size_t n,
                const params &prm = params(),
                const backend_params &backend_prm = backend_params(),
                const InnerProduct &inner_product = InnerProduct()
          ) : prm(prm), n(n),
              r(Backend::create_vector(n, backend_prm)),
              s(Backend::create_vector(n, backend_prm)),
              p(Backend::create_vector(n, backend_prm)),
              q(Backend::create_vector(n, backend_prm)),
              inner_product(inner_product)
        { }

        /* Computes the solution for the given system matrix \p A and the
         * right-hand side \p rhs.  Returns the number of iterations made and
         * the achieved residual as a ``boost::tuple``. The solution vector
         * \p x provides initial approximation in input and holds the computed
         * solution on output.
         *
         * The system matrix may differ from the matrix used during
         * initialization. This may be used for the solution of non-stationary
         * problems with slowly changing coefficients. There is a strong chance
         * that a preconditioner built for a time step will act as a reasonably
         * good preconditioner for several subsequent time steps [DeSh12]_.
         */
        template <class Matrix, class Precond, class Vec1, class Vec2>
        boost::tuple<size_t, scalar_type> operator()(
                Matrix  const &A,
                Precond const &P,
                Vec1    const &rhs,
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
                Vec2          &x
#else
                Vec2          &&x
#endif
                ) const
        {
            static const coef_type one  = math::identity<coef_type>();
            static const coef_type zero = math::zero<coef_type>();

            backend::residual(rhs, A, x, *r);
            scalar_type norm_rhs = norm(rhs);
            if (norm_rhs < amgcl::detail::eps<scalar_type>(n)) {
                backend::clear(x);
                return boost::make_tuple(0, norm_rhs);
            }

            scalar_type eps  = std::max(prm.tol * norm_rhs, prm.abstol);

            coef_type rho1 = 2 * eps * one;
            coef_type rho2 = zero;
            scalar_type res_norm = norm(*r);

            size_t iter = 0;
            for(; iter < prm.maxiter && math::norm(res_norm) > eps; ++iter) {
                P.apply(*r, *s);

                rho2 = rho1;
                rho1 = inner_product(*r, *s);

                if (iter)
                    backend::axpby(one, *s, rho1 / rho2, *p);
                else
                    backend::copy(*s, *p);

                backend::spmv(one, A, *p, zero, *q);

                coef_type alpha = rho1 / inner_product(*q, *p);

                backend::axpby( alpha, *p, one,  x);
                backend::axpby(-alpha, *q, one, *r);

                res_norm = norm(*r);
            }

            return boost::make_tuple(iter, res_norm / norm_rhs);
        }

        /* Computes the solution for the given right-hand side \p rhs. The
         * system matrix is the same that was used for the setup of the
         * preconditioner \p P.  Returns the number of iterations made and the
         * achieved residual as a ``boost::tuple``. The solution vector \p x
         * provides initial approximation in input and holds the computed
         * solution on output.
         */
        template <class Precond, class Vec1, class Vec2>
        boost::tuple<size_t, scalar_type> operator()(
                Precond const &P,
                Vec1    const &rhs,
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
                Vec2          &x
#else
                Vec2          &&x
#endif
                ) const
        {
            return (*this)(P.system_matrix(), P, rhs, x);
        }

        friend std::ostream& operator<<(std::ostream &os, const cg &s) {
            return os << "cg: " << s.n << " unknowns";
        }
    public:
        params prm;

    private:
        size_t n;

        boost::shared_ptr<vector> r;
        boost::shared_ptr<vector> s;
        boost::shared_ptr<vector> p;
        boost::shared_ptr<vector> q;

        InnerProduct inner_product;

        template <class Vec>
        scalar_type norm(const Vec &x) const {
            return sqrt(math::norm(inner_product(x, x)));
        }
};

} // namespace solver
} // namespace amgcl

#endif
<|endoftext|>


<commit_before>// Filename: withOutputFile.cxx
// Created by:  drose (11Apr01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University.  All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license.  You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

#include "withOutputFile.h"
#include "executionEnvironment.h"
#include "zStream.h"

#include "pnotify.h"

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::Constructor
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
WithOutputFile::
WithOutputFile(bool allow_last_param, bool allow_stdout,
               bool binary_output) {
  _allow_last_param = allow_last_param;
  _allow_stdout = allow_stdout;
  _binary_output = binary_output;
  _got_output_filename = false;
  _output_ptr = (ostream *)NULL;
  _owns_output_ptr = false;
}

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::Destructor
//       Access: Public, Virtual
//  Description:
////////////////////////////////////////////////////////////////////
WithOutputFile::
~WithOutputFile() {
  if (_owns_output_ptr) {
    delete _output_ptr;
    _owns_output_ptr = false;
  }
}

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::get_output
//       Access: Public
//  Description: Returns an output stream that corresponds to the
//               user's intended egg file output--either stdout, or
//               the named output file.
////////////////////////////////////////////////////////////////////
ostream &WithOutputFile::
get_output() {
  if (_output_ptr == (ostream *)NULL) {
    if (!_got_output_filename) {
      // No filename given; use standard output.
      if (!_allow_stdout) {
        nout << "No output filename specified.\n";
        exit(1);
      }
      _output_ptr = &cout;
      _owns_output_ptr = false;

    } else {
      // Attempt to open the named file.
      unlink(_output_filename.c_str());
      _output_filename.make_dir();

      bool pz_file = false;
#ifdef HAVE_ZLIB
      if (_output_filename.get_extension() == "pz") {
        // The filename ends in .pz, which means to automatically compress
        // the file that we write.
        pz_file = true;
      }
#endif  // HAVE_ZLIB

      if (_binary_output || pz_file) {
        _output_filename.set_binary();
      } else {
        _output_filename.set_text();
      }

      if (!_output_filename.open_write(_output_stream)) {
        nout << "Unable to write to " << _output_filename << "\n";
        exit(1);
      }
      nout << "Writing " << _output_filename << "\n";
      _output_ptr = &_output_stream;
      _owns_output_ptr = false;

#ifdef HAVE_ZLIB
      if (pz_file) {
        _output_ptr = new OCompressStream(_output_ptr, _owns_output_ptr);
        _owns_output_ptr = true;
      }
#endif  // HAVE_ZLIB
    }
  }
  return *_output_ptr;
}

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::has_output_filename
//       Access: Public
//  Description: Returns true if the user specified an output
//               filename, false otherwise (e.g. the output file is
//               implicitly stdout).
////////////////////////////////////////////////////////////////////
bool WithOutputFile::
has_output_filename() const {
  return _got_output_filename;
}

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::get_output_filename
//       Access: Public
//  Description: If has_output_filename() returns true, this is the
//               filename that the user specified.  Otherwise, it
//               returns the empty string.
////////////////////////////////////////////////////////////////////
Filename WithOutputFile::
get_output_filename() const {
  if (_got_output_filename) {
    return _output_filename;
  }
  return Filename();
}

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::check_last_arg
//       Access: Protected
//  Description: Checks if the last filename on the argument list is
//               a file with the expected extension (if
//               _allow_last_param was set true), and removes it from
//               the argument list if it is.  Returns true if the
//               arguments are good, false if something is invalid.
//
//               minimum_args is the number of arguments we know must
//               be input parameters and therefore cannot be
//               interpreted as output filenames.
////////////////////////////////////////////////////////////////////
bool WithOutputFile::
check_last_arg(ProgramBase::Args &args, int minimum_args) {
  if (_allow_last_param && !_got_output_filename &&
      (int)args.size() > minimum_args) {
    Filename filename = Filename::from_os_specific(args.back());

    if (!_preferred_extension.empty() &&
        ("." + filename.get_extension()) != _preferred_extension) {
      // This argument must not be an output filename.
      if (!_allow_stdout) {
        nout << "Output filename " << filename
             << " does not end in " << _preferred_extension
             << ".  If this is really what you intended, "
          "use the -o output_file syntax.\n";
        return false;
      }

    } else {
      // This argument appears to be an output filename.
      _got_output_filename = true;
      _output_filename = filename;
      args.pop_back();

      if (!verify_output_file_safe()) {
        return false;
      }
    }
  }

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::verify_output_file_safe
//       Access: Protected
//  Description: This is called when the output file is given as the
//               last parameter on the command line.  Since this is a
//               fairly dangerous way to specify the output file (it's
//               easy to accidentally overwrite an input file this
//               way), the convention is to disallow this syntax if
//               the output file already exists.
//
//               This function will test if the output file exists,
//               and issue a warning message if it does, returning
//               false.  If all is well, it will return true.
////////////////////////////////////////////////////////////////////
bool WithOutputFile::
verify_output_file_safe() const {
  nassertr(_got_output_filename, false);

  if (_output_filename.exists()) {
    nout << "The output filename " << _output_filename << " already exists.  "
      "If you wish to overwrite it, you must use the -o option to specify "
      "the output filename, instead of simply specifying it as the last "
      "parameter.\n";
    return false;
  }
  return true;
}
<commit_msg>clear error flag<commit_after>// Filename: withOutputFile.cxx
// Created by:  drose (11Apr01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University.  All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license.  You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

#include "withOutputFile.h"
#include "executionEnvironment.h"
#include "zStream.h"

#include "pnotify.h"

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::Constructor
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
WithOutputFile::
WithOutputFile(bool allow_last_param, bool allow_stdout,
               bool binary_output) {
  _allow_last_param = allow_last_param;
  _allow_stdout = allow_stdout;
  _binary_output = binary_output;
  _got_output_filename = false;
  _output_ptr = (ostream *)NULL;
  _owns_output_ptr = false;
}

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::Destructor
//       Access: Public, Virtual
//  Description:
////////////////////////////////////////////////////////////////////
WithOutputFile::
~WithOutputFile() {
  if (_owns_output_ptr) {
    delete _output_ptr;
    _owns_output_ptr = false;
  }
}

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::get_output
//       Access: Public
//  Description: Returns an output stream that corresponds to the
//               user's intended egg file output--either stdout, or
//               the named output file.
////////////////////////////////////////////////////////////////////
ostream &WithOutputFile::
get_output() {
  if (_output_ptr == (ostream *)NULL) {
    if (!_got_output_filename) {
      // No filename given; use standard output.
      if (!_allow_stdout) {
        nout << "No output filename specified.\n";
        exit(1);
      }
      _output_ptr = &cout;
      _owns_output_ptr = false;

    } else {
      // Attempt to open the named file.
      unlink(_output_filename.c_str());
      _output_filename.make_dir();

      bool pz_file = false;
#ifdef HAVE_ZLIB
      if (_output_filename.get_extension() == "pz") {
        // The filename ends in .pz, which means to automatically compress
        // the file that we write.
        pz_file = true;
      }
#endif  // HAVE_ZLIB

      if (_binary_output || pz_file) {
        _output_filename.set_binary();
      } else {
        _output_filename.set_text();
      }

      _output_stream.clear();
      if (!_output_filename.open_write(_output_stream)) {
        nout << "Unable to write to " << _output_filename << "\n";
        exit(1);
      }
      nout << "Writing " << _output_filename << "\n";
      _output_ptr = &_output_stream;
      _owns_output_ptr = false;

#ifdef HAVE_ZLIB
      if (pz_file) {
        _output_ptr = new OCompressStream(_output_ptr, _owns_output_ptr);
        _owns_output_ptr = true;
      }
#endif  // HAVE_ZLIB
    }
  }
  return *_output_ptr;
}

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::has_output_filename
//       Access: Public
//  Description: Returns true if the user specified an output
//               filename, false otherwise (e.g. the output file is
//               implicitly stdout).
////////////////////////////////////////////////////////////////////
bool WithOutputFile::
has_output_filename() const {
  return _got_output_filename;
}

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::get_output_filename
//       Access: Public
//  Description: If has_output_filename() returns true, this is the
//               filename that the user specified.  Otherwise, it
//               returns the empty string.
////////////////////////////////////////////////////////////////////
Filename WithOutputFile::
get_output_filename() const {
  if (_got_output_filename) {
    return _output_filename;
  }
  return Filename();
}

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::check_last_arg
//       Access: Protected
//  Description: Checks if the last filename on the argument list is
//               a file with the expected extension (if
//               _allow_last_param was set true), and removes it from
//               the argument list if it is.  Returns true if the
//               arguments are good, false if something is invalid.
//
//               minimum_args is the number of arguments we know must
//               be input parameters and therefore cannot be
//               interpreted as output filenames.
////////////////////////////////////////////////////////////////////
bool WithOutputFile::
check_last_arg(ProgramBase::Args &args, int minimum_args) {
  if (_allow_last_param && !_got_output_filename &&
      (int)args.size() > minimum_args) {
    Filename filename = Filename::from_os_specific(args.back());

    if (!_preferred_extension.empty() &&
        ("." + filename.get_extension()) != _preferred_extension) {
      // This argument must not be an output filename.
      if (!_allow_stdout) {
        nout << "Output filename " << filename
             << " does not end in " << _preferred_extension
             << ".  If this is really what you intended, "
          "use the -o output_file syntax.\n";
        return false;
      }

    } else {
      // This argument appears to be an output filename.
      _got_output_filename = true;
      _output_filename = filename;
      args.pop_back();

      if (!verify_output_file_safe()) {
        return false;
      }
    }
  }

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: WithOutputFile::verify_output_file_safe
//       Access: Protected
//  Description: This is called when the output file is given as the
//               last parameter on the command line.  Since this is a
//               fairly dangerous way to specify the output file (it's
//               easy to accidentally overwrite an input file this
//               way), the convention is to disallow this syntax if
//               the output file already exists.
//
//               This function will test if the output file exists,
//               and issue a warning message if it does, returning
//               false.  If all is well, it will return true.
////////////////////////////////////////////////////////////////////
bool WithOutputFile::
verify_output_file_safe() const {
  nassertr(_got_output_filename, false);

  if (_output_filename.exists()) {
    nout << "The output filename " << _output_filename << " already exists.  "
      "If you wish to overwrite it, you must use the -o option to specify "
      "the output filename, instead of simply specifying it as the last "
      "parameter.\n";
    return false;
  }
  return true;
}
<|endoftext|>


<commit_before>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_SoundRuler.h
 *  @brief  EC_SoundRuler enables visual sound properties effect for scene entity.
 *  @note   The entity must have EC_OgrePlaceable and EC_OpenSimPrim
 *  @author Nathan Letwory | http://www.letworyinteractive.com
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"
#include "EC_SoundRuler.h"
#include "ModuleInterface.h"
#include "Entity.h"
#include "Renderer.h"
#include "OgreMaterialUtils.h"
#include "EC_OgrePlaceable.h"
#include "EC_OgreMesh.h"
#include "EC_OgreCustomObject.h"
#include "EC_OpenSimPrim.h"
#include "LoggingFunctions.h"
#include "RexUUID.h"
#include <Ogre.h>

DEFINE_POCO_LOGGING_FUNCTIONS("EC_SoundRuler")

#include "MemoryLeakCheck.h"

EC_SoundRuler::EC_SoundRuler(Foundation::ModuleInterface *module) :
    Foundation::ComponentInterface(module->GetFramework()),
    radiusAttr_(this, "radius", 5),
    volumeAttr_(this, "volume", 5),
    segmentsAttr_(this, "segments", 29),
    rulerObject(0),
    sceneNode_(0)
{
    renderer_ = module->GetFramework()->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer);

    QObject::connect(this, SIGNAL(OnChanged()), this, SLOT(UpdateSoundRuler()));

    RexUUID uuid = RexUUID::CreateRandom();
    rulerName = uuid.ToString() + "ruler";
    nodeName = uuid.ToString() + "node";
}

EC_SoundRuler::~EC_SoundRuler()
{
    // OgreRendering module might be already deleted. If so, the cloned entity is also already deleted.
    // In this case, just set pointer to 0.
    if (!renderer_.expired())
    {
        Ogre::SceneManager *sceneMgr = renderer_.lock()->GetSceneManager();
            sceneMgr->destroyManualObject(rulerObject);
    }
    else
    {
        rulerObject = 0;
        sceneNode_ = 0;
    }
}

void  EC_SoundRuler::Show()
{
    if (!rulerObject)
        Create();

    if (!rulerObject)
    {
        LogError("EC_SoundRuler not initialized properly.");
        return;
    }

    if (rulerObject)
        rulerObject->setVisible(true);
}

void  EC_SoundRuler::Hide()
{
    if (!rulerObject)
        Create();

    if (!rulerObject)
    {
        LogError("EC_SoundRuler not initialized properly.");
        return;
    }

    if (rulerObject)
        rulerObject->setVisible(false);
}

bool EC_SoundRuler::IsVisible() const
{
    if (rulerObject)
        return rulerObject->isVisible();

    return false;
}

void EC_SoundRuler::Create()
{
    if (renderer_.expired())
        return;

    Ogre::SceneManager *scene_mgr= renderer_.lock()->GetSceneManager();
    assert(scene_mgr);
    if (!scene_mgr)
        return;

    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (!entity)
        return;

    OgreRenderer::EC_OgrePlaceable *placeable = entity->GetComponent<OgreRenderer::EC_OgrePlaceable>().get();
    assert(placeable);
    if (!placeable)
        return;
    sceneNode_ = placeable->GetSceneNode();

    assert(sceneNode_);
    if (!sceneNode_)
        return;

    if(scene_mgr->hasManualObject(rulerName)) {
        rulerObject = scene_mgr->getManualObject(rulerName);
        if(rulerObject->isAttached())
#if OGRE_VERSION_MINOR <= 6 && OGRE_VERSION_MAJOR <= 1
            rulerObject->detatchFromParent();
#else
            rulerObject->detachFromParent();
#endif
    } else {
        rulerObject = scene_mgr->createManualObject(rulerName);
    }

    SetupSoundRuler();

    // get soundRulerNode only when we are working in world space
    if(scene_mgr->hasSceneNode(nodeName)) {
        globalSceneNode = scene_mgr->getSceneNode(nodeName);
    } else {
        globalSceneNode = scene_mgr->getRootSceneNode()->createChildSceneNode(nodeName);
        globalSceneNode->setVisible(true);
    }
    assert(globalSceneNode);
    if(!globalSceneNode)
        return;

    globalSceneNode->setPosition(sceneNode_->getParent()->getPosition());
    globalSceneNode->attachObject(rulerObject);
}

void EC_SoundRuler::SetupSoundRuler()
{
    if(!rulerObject)
        return;

    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (!entity)
        return;

    EC_OpenSimPrim *prim = entity->GetComponent<EC_OpenSimPrim>().get();
    assert(prim);
    if(!prim)
        return;

    float const radius = prim->SoundRadius;
    float const volume = prim->SoundVolume;
    float const segments = segmentsAttr_.Get();
    unsigned int const spikeInterval = (unsigned int)(segments / 4.0);

    rulerObject->clear();
    rulerObject->setCastShadows(false);
    rulerObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_STRIP);

    unsigned int i = 0;
    unsigned int j = 0;
    for(float theta = 0; theta <= 2 * Ogre::Math::PI; theta += Ogre::Math::PI / segments) {
        rulerObject->position(radius * cos(theta), radius * sin(theta), 0);
        rulerObject->index(i++);
        if(j % spikeInterval == 0) {
            rulerObject->position(radius * cos(theta), radius * sin(theta), volume);
            rulerObject->index(i++);
            rulerObject->position(radius * cos(theta), radius * sin(theta), 0);
            rulerObject->index(i++);
        }
        j++;
    }
    rulerObject->index(0); // Close the line = circle
    rulerObject->end();
}

void EC_SoundRuler::UpdateSoundRuler() {
    Create();
    Show();
}

<commit_msg>Remove unnecessary checks.<commit_after>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_SoundRuler.h
 *  @brief  EC_SoundRuler enables visual sound properties effect for scene entity.
 *  @note   The entity must have EC_OgrePlaceable and EC_OpenSimPrim
 *  @author Nathan Letwory | http://www.letworyinteractive.com
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"
#include "EC_SoundRuler.h"
#include "ModuleInterface.h"
#include "Entity.h"
#include "Renderer.h"
#include "OgreMaterialUtils.h"
#include "EC_OgrePlaceable.h"
#include "EC_OgreMesh.h"
#include "EC_OgreCustomObject.h"
#include "EC_OpenSimPrim.h"
#include "LoggingFunctions.h"
#include "RexUUID.h"
#include <Ogre.h>

DEFINE_POCO_LOGGING_FUNCTIONS("EC_SoundRuler")

#include "MemoryLeakCheck.h"

EC_SoundRuler::EC_SoundRuler(Foundation::ModuleInterface *module) :
    Foundation::ComponentInterface(module->GetFramework()),
    radiusAttr_(this, "radius", 5),
    volumeAttr_(this, "volume", 5),
    segmentsAttr_(this, "segments", 29),
    rulerObject(0),
    sceneNode_(0)
{
    renderer_ = module->GetFramework()->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer);

    QObject::connect(this, SIGNAL(OnChanged()), this, SLOT(UpdateSoundRuler()));

    RexUUID uuid = RexUUID::CreateRandom();
    rulerName = uuid.ToString() + "ruler";
    nodeName = uuid.ToString() + "node";
}

EC_SoundRuler::~EC_SoundRuler()
{
    // OgreRendering module might be already deleted. If so, the cloned entity is also already deleted.
    // In this case, just set pointer to 0.
    if (!renderer_.expired())
    {
        Ogre::SceneManager *sceneMgr = renderer_.lock()->GetSceneManager();
            sceneMgr->destroyManualObject(rulerObject);
    }
    else
    {
        rulerObject = 0;
        sceneNode_ = 0;
    }
}

void  EC_SoundRuler::Show()
{
    if (!rulerObject)
        Create();

    if (!rulerObject)
    {
        LogError("EC_SoundRuler not initialized properly.");
        return;
    }

    rulerObject->setVisible(true);
}

void  EC_SoundRuler::Hide()
{
    if (!rulerObject)
        Create();

    if (!rulerObject)
    {
        LogError("EC_SoundRuler not initialized properly.");
        return;
    }

    rulerObject->setVisible(false);
}

bool EC_SoundRuler::IsVisible() const
{
    if (rulerObject)
        return rulerObject->isVisible();

    return false;
}

void EC_SoundRuler::Create()
{
    if (renderer_.expired())
        return;

    Ogre::SceneManager *scene_mgr= renderer_.lock()->GetSceneManager();
    assert(scene_mgr);
    if (!scene_mgr)
        return;

    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (!entity)
        return;

    OgreRenderer::EC_OgrePlaceable *placeable = entity->GetComponent<OgreRenderer::EC_OgrePlaceable>().get();
    assert(placeable);
    if (!placeable)
        return;
    sceneNode_ = placeable->GetSceneNode();

    assert(sceneNode_);
    if (!sceneNode_)
        return;

    if(scene_mgr->hasManualObject(rulerName)) {
        rulerObject = scene_mgr->getManualObject(rulerName);
        if(rulerObject->isAttached())
#if OGRE_VERSION_MINOR <= 6 && OGRE_VERSION_MAJOR <= 1
            rulerObject->detatchFromParent();
#else
            rulerObject->detachFromParent();
#endif
    } else {
        rulerObject = scene_mgr->createManualObject(rulerName);
    }

    SetupSoundRuler();

    // get soundRulerNode only when we are working in world space
    if(scene_mgr->hasSceneNode(nodeName)) {
        globalSceneNode = scene_mgr->getSceneNode(nodeName);
    } else {
        globalSceneNode = scene_mgr->getRootSceneNode()->createChildSceneNode(nodeName);
        globalSceneNode->setVisible(true);
    }
    assert(globalSceneNode);
    if(!globalSceneNode)
        return;

    globalSceneNode->setPosition(sceneNode_->getParent()->getPosition());
    globalSceneNode->attachObject(rulerObject);
}

void EC_SoundRuler::SetupSoundRuler()
{
    if(!rulerObject)
        return;

    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (!entity)
        return;

    EC_OpenSimPrim *prim = entity->GetComponent<EC_OpenSimPrim>().get();
    assert(prim);
    if(!prim)
        return;

    float const radius = prim->SoundRadius;
    float const volume = prim->SoundVolume;
    float const segments = segmentsAttr_.Get();
    unsigned int const spikeInterval = (unsigned int)(segments / 4.0);

    rulerObject->clear();
    rulerObject->setCastShadows(false);
    rulerObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_STRIP);

    unsigned int i = 0;
    unsigned int j = 0;
    for(float theta = 0; theta <= 2 * Ogre::Math::PI; theta += Ogre::Math::PI / segments) {
        rulerObject->position(radius * cos(theta), radius * sin(theta), 0);
        rulerObject->index(i++);
        if(j % spikeInterval == 0) {
            rulerObject->position(radius * cos(theta), radius * sin(theta), volume);
            rulerObject->index(i++);
            rulerObject->position(radius * cos(theta), radius * sin(theta), 0);
            rulerObject->index(i++);
        }
        j++;
    }
    rulerObject->index(0); // Close the line = circle
    rulerObject->end();
}

void EC_SoundRuler::UpdateSoundRuler() {
    Create();
    Show();
}

<|endoftext|>


<commit_before><commit_msg>We need to sniff from file:// URLs so that we don't do silly things like try to download README files.<commit_after><|endoftext|>