<commit_before>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  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.

******************************************************************************/
#include "LoadDataReaction.h"

#include "ActiveObjects.h"
#include "DataSource.h"
#include "EmdFormat.h"
#include "ModuleManager.h"
#include "Pipeline.h"
#include "PipelineManager.h"
#include "RAWFileReaderDialog.h"
#include "RecentFilesMenu.h"
#include "Utilities.h"

#include <pqActiveObjects.h>
#include <pqLoadDataReaction.h>
#include <pqPipelineSource.h>
#include <pqProxyWidgetDialog.h>
#include <pqRenderView.h>
#include <pqSMAdaptor.h>
#include <pqView.h>
#include <vtkSMCoreUtilities.h>
#include <vtkSMParaViewPipelineController.h>
#include <vtkSMPropertyHelper.h>
#include <vtkSMSessionProxyManager.h>
#include <vtkSMSourceProxy.h>
#include <vtkSMStringVectorProperty.h>
#include <vtkSMViewProxy.h>

#include <vtkImageData.h>
#include <vtkNew.h>
#include <vtkPointData.h>
#include <vtkSmartPointer.h>
#include <vtkTrivialProducer.h>

#include <QDebug>
#include <QFileDialog>
#include <QFileInfo>
#include <QJsonArray>

#include <sstream>

namespace {
bool hasData(vtkSMProxy* reader)
{
  vtkSMSourceProxy* dataSource = vtkSMSourceProxy::SafeDownCast(reader);
  if (!dataSource) {
    return false;
  }

  dataSource->UpdatePipeline();
  vtkAlgorithm* vtkalgorithm =
    vtkAlgorithm::SafeDownCast(dataSource->GetClientSideObject());
  if (!vtkalgorithm) {
    return false;
  }

  // Create a clone and release the reader data.
  vtkImageData* data =
    vtkImageData::SafeDownCast(vtkalgorithm->GetOutputDataObject(0));
  if (!data) {
    return false;
  }

  int extent[6];
  data->GetExtent(extent);
  if (extent[0] > extent[1] || extent[2] > extent[3] || extent[4] > extent[5]) {
    return false;
  }

  vtkPointData* pd = data->GetPointData();
  if (!pd) {
    return false;
  }

  if (pd->GetNumberOfArrays() < 1) {
    return false;
  }
  return true;
}
}

namespace tomviz {

LoadDataReaction::LoadDataReaction(QAction* parentObject)
  : pqReaction(parentObject)
{
}

LoadDataReaction::~LoadDataReaction() = default;

void LoadDataReaction::onTriggered()
{
  loadData();
}

QList<DataSource*> LoadDataReaction::loadData()
{
  QStringList filters;
  filters
    << "Common file types (*.emd *.jpg *.jpeg *.png *.tiff *.tif *.raw"
       " *.dat *.bin *.txt *.mhd *.mha *.vti *.mrc *.st *.rec *.ali *.xmf *.xdmf)"
    << "EMD (*.emd)"
    << "JPeg Image files (*.jpg *.jpeg)"
    << "PNG Image files (*.png)"
    << "TIFF Image files (*.tiff *.tif)"
    << "OME-TIFF Image files (*.ome.tif)"
    << "Raw data files (*.raw *.dat *.bin)"
    << "Meta Image files (*.mhd *.mha)"
    << "VTK ImageData Files (*.vti)"
    << "MRC files (*.mrc *.st *.rec *.ali)"
    << "XDMF files (*.xmf *.xdmf)"
    << "Text files (*.txt)"
    << "All files (*.*)";

  QFileDialog dialog(nullptr);
  dialog.setFileMode(QFileDialog::ExistingFiles);
  dialog.setNameFilters(filters);
  dialog.setObjectName("FileOpenDialog-tomviz"); // avoid name collision?

  QList<DataSource*> dataSources;
  if (dialog.exec()) {
    QStringList filenames = dialog.selectedFiles();
    dataSources << loadData(filenames);
  }

  return dataSources;
}

DataSource* LoadDataReaction::loadData(const QString& fileName,
                                       bool defaultModules, bool addToRecent,
                                       bool child, const QJsonObject& options)
{
  QJsonObject opts = options;
  opts["defaultModules"] = defaultModules;
  opts["addToRecent"] = addToRecent;
  opts["child"] = child;
  return LoadDataReaction::loadData(fileName, opts);
}

DataSource* LoadDataReaction::loadData(const QString& fileName,
                                       const QJsonObject& val)
{
  QStringList fileNames;
  fileNames << fileName;

  return loadData(fileNames, val);
}

DataSource* LoadDataReaction::loadData(const QStringList& fileNames,
                                       const QJsonObject& options)
{
  bool defaultModules = options["defaultModules"].toBool(true);
  bool addToRecent = options["addToRecent"].toBool(true);
  bool child = options["child"].toBool(false);

  DataSource* dataSource(nullptr);
  QString firstFile;
  if (fileNames.size() > 0) {
    firstFile = fileNames[0];
  }
  QFileInfo info(firstFile);
  if (info.suffix().toLower() == "emd") {
    // Load the file using our simple EMD class.
    EmdFormat emdFile;
    vtkNew<vtkImageData> imageData;
    if (emdFile.read(firstFile.toLatin1().data(), imageData)) {
      dataSource = new DataSource(imageData);
      LoadDataReaction::dataSourceAdded(dataSource, defaultModules, child);
    }
  } else if (info.completeSuffix().endsWith("ome.tif")) {
    auto pxm = tomviz::ActiveObjects::instance().proxyManager();
    const char* name = "OMETIFFReader";
    vtkSmartPointer<vtkSMProxy> source;
    source.TakeReference(pxm->NewProxy("sources", name));
    QString pname = vtkSMCoreUtilities::GetFileNameProperty(source);
    vtkSMStringVectorProperty* prop = vtkSMStringVectorProperty::SafeDownCast(
      source->GetProperty(pname.toUtf8().data()));
    pqSMAdaptor::setElementProperty(prop, firstFile);
    source->UpdateVTKObjects();

    dataSource = createDataSource(source, defaultModules, child);
    QJsonObject readerProperties;
    readerProperties["name"] = name;
    dataSource->setReaderProperties(readerProperties.toVariantMap());
  } else if (options.contains("reader")) {
    // Create the ParaView reader and set its properties using the JSON
    // configuration.
    auto props = options["reader"].toObject();
    auto name = props["name"].toString();

    auto pxm = ActiveObjects::instance().proxyManager();
    vtkSmartPointer<vtkSMProxy> reader;
    reader.TakeReference(pxm->NewProxy("sources", name.toLatin1().data()));

    setProperties(props, reader);
    setFileNameProperties(props, reader);
    reader->UpdateVTKObjects();
    vtkSMSourceProxy::SafeDownCast(reader)->UpdatePipelineInformation();
    dataSource =
      LoadDataReaction::createDataSource(reader, defaultModules, child);
    if (dataSource == nullptr) {
      return nullptr;
    }

    dataSource->setReaderProperties(props.toVariantMap());

  } else {
    // Use ParaView's file load infrastructure.
    pqPipelineSource* reader = pqLoadDataReaction::loadData(fileNames);
    if (!reader) {
      return nullptr;
    }

    dataSource = createDataSource(reader->getProxy(), defaultModules, child);
    if (dataSource == nullptr) {
      return nullptr;
    }

    QJsonObject props = readerProperties(reader->getProxy());
    props["name"] = reader->getProxy()->GetXMLName();

    dataSource->setReaderProperties(props.toVariantMap());

    vtkNew<vtkSMParaViewPipelineController> controller;
    controller->UnRegisterProxy(reader->getProxy());
  }

  // It is possible that the dataSource will be null if, for example, loading
  // a VTI is cancelled in the array selection dialog. Guard against this.
  if (!dataSource) {
    return nullptr;
  }

  // Now for house keeping, registering elements, etc.
  // AG: always save it as a list, even if there is only one file.
  dataSource->setFileNames(fileNames);
  // dataSource->setFileName(fileName);
  // if (fileNames.size() > 1) {

  // }
  if (addToRecent && dataSource) {
    RecentFilesMenu::pushDataReader(dataSource);
  }
  return dataSource;
}

DataSource* LoadDataReaction::createDataSource(vtkSMProxy* reader,
                                               bool defaultModules, bool child)
{
  // Prompt user for reader configuration, unless it is TIFF.
  QScopedPointer<QDialog> dialog(new pqProxyWidgetDialog(reader));
  bool hasVisibleWidgets =
    qobject_cast<pqProxyWidgetDialog*>(dialog.data())->hasVisibleWidgets();
  if (QString(reader->GetXMLName()) == "TVRawImageReader") {
    dialog.reset(new RAWFileReaderDialog(reader));
    hasVisibleWidgets = true;
    // This will show only a partial filename when reading multiple files as a
    // raw image
    vtkSMPropertyHelper fname(reader, "FilePrefix");
    QFileInfo info(fname.GetAsString());
    dialog->setWindowTitle(QString("Opening %1").arg(info.fileName()));
  } else {
    dialog->setWindowTitle("Configure Reader Parameters");
  }
  dialog->setObjectName("ConfigureReaderDialog");
  if (QString(reader->GetXMLName()) == "TIFFSeriesReader" ||
      hasVisibleWidgets == false || dialog->exec() == QDialog::Accepted) {

    if (!hasData(reader)) {
      qCritical() << "Error: failed to load file!";
      return nullptr;
    }

    auto source = vtkSMSourceProxy::SafeDownCast(reader);
    source->UpdatePipeline();
    auto algo = vtkAlgorithm::SafeDownCast(source->GetClientSideObject());
    auto data = algo->GetOutputDataObject(0);
    auto image = vtkImageData::SafeDownCast(data);

    DataSource* dataSource = new DataSource(image);
    // Do whatever we need to do with a new data source.
    LoadDataReaction::dataSourceAdded(dataSource, defaultModules, child);
    return dataSource;
  }
  return nullptr;
}

void LoadDataReaction::dataSourceAdded(DataSource* dataSource,
                                       bool defaultModules, bool child)
{
  if (!dataSource) {
    return;
  }
  DataSource* previousActiveDataSource =
    ActiveObjects::instance().activeDataSource();
  bool oldMoveObjectsEnabled = ActiveObjects::instance().moveObjectsEnabled();
  ActiveObjects::instance().setMoveObjectsMode(false);
  if (child) {
    ModuleManager::instance().addChildDataSource(dataSource);
  } else {
    auto pipeline = new Pipeline(dataSource);
    PipelineManager::instance().addPipeline(pipeline);
    // TODO Eventually we shouldn't need to keep track of the data sources,
    // the pipeline should do that for us.
    ModuleManager::instance().addDataSource(dataSource);
    if (defaultModules) {
      pipeline->addDefaultModules(dataSource);
    }
  }

  // Work through pathological cases as necessary, prefer active view.
  ActiveObjects::instance().createRenderViewIfNeeded();
  auto view = ActiveObjects::instance().activeView();

  if (!view || QString(view->GetXMLName()) != "RenderView") {
    ActiveObjects::instance().setActiveViewToFirstRenderView();
    view = ActiveObjects::instance().activeView();
  }

  ActiveObjects::instance().setMoveObjectsMode(oldMoveObjectsEnabled);
  if (!previousActiveDataSource) {
    pqRenderView* renderView =
      qobject_cast<pqRenderView*>(pqActiveObjects::instance().activeView());
    if (renderView) {
      tomviz::createCameraOrbit(dataSource->proxy(),
                                renderView->getRenderViewProxy());
    }
  }
}

QJsonObject LoadDataReaction::readerProperties(vtkSMProxy* reader)
{
  QStringList propNames({ "DataScalarType", "DataByteOrder",
                          "NumberOfScalarComponents", "DataExtent" });

  QJsonObject props;
  foreach (QString propName, propNames) {
    auto prop = reader->GetProperty(propName.toLatin1().data());
    if (prop != nullptr) {
      props[propName] = toJson(prop);
    }
  }

  // Special case file name related properties
  auto prop = reader->GetProperty("FileName");
  if (prop != nullptr) {
    props["fileName"] = toJson(prop);
  }
  prop = reader->GetProperty("FileNames");
  if (prop != nullptr) {
    auto fileNames = toJson(prop).toArray();
    if (fileNames.size() > 1) {
      props["fileNames"] = fileNames;
    }
    // Normalize to fileNames for single value.
    else {
      props["fileName"] = fileNames[0];
    }
  }
  prop = reader->GetProperty("FilePrefix");
  if (prop != nullptr) {
    props["fileName"] = toJson(prop);
  }

  return props;
}

void LoadDataReaction::setFileNameProperties(const QJsonObject& props,
                                             vtkSMProxy* reader)
{
  auto prop = reader->GetProperty("FileName");
  if (prop != nullptr) {
    if (!props.contains("fileName")) {
      qCritical() << "Reader doesn't have 'fileName' property.";
      return;
    }
    tomviz::setProperty(props["fileName"], prop);
  }
  prop = reader->GetProperty("FileNames");
  if (prop != nullptr) {
    if (!props.contains("fileNames") && !props.contains("fileName")) {
      qCritical() << "Reader doesn't have 'fileName' or 'fileNames' property.";
      return;
    }

    if (props.contains("fileNames")) {
      tomviz::setProperty(props["fileNames"], prop);
    } else {
      QJsonArray fileNames;
      fileNames.append(props["fileName"]);
      tomviz::setProperty(fileNames, prop);
    }
  }
  prop = reader->GetProperty("FilePrefix");
  if (prop != nullptr) {
    if (!props.contains("fileName")) {
      qCritical() << "Reader doesn't have 'fileName' property.";
      return;
    }
    tomviz::setProperty(props["fileName"], prop);
  }
}

} // end of namespace tomviz
<commit_msg>cleanup comments<commit_after>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  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.

******************************************************************************/
#include "LoadDataReaction.h"

#include "ActiveObjects.h"
#include "DataSource.h"
#include "EmdFormat.h"
#include "ModuleManager.h"
#include "Pipeline.h"
#include "PipelineManager.h"
#include "RAWFileReaderDialog.h"
#include "RecentFilesMenu.h"
#include "Utilities.h"

#include <pqActiveObjects.h>
#include <pqLoadDataReaction.h>
#include <pqPipelineSource.h>
#include <pqProxyWidgetDialog.h>
#include <pqRenderView.h>
#include <pqSMAdaptor.h>
#include <pqView.h>
#include <vtkSMCoreUtilities.h>
#include <vtkSMParaViewPipelineController.h>
#include <vtkSMPropertyHelper.h>
#include <vtkSMSessionProxyManager.h>
#include <vtkSMSourceProxy.h>
#include <vtkSMStringVectorProperty.h>
#include <vtkSMViewProxy.h>

#include <vtkImageData.h>
#include <vtkNew.h>
#include <vtkPointData.h>
#include <vtkSmartPointer.h>
#include <vtkTrivialProducer.h>

#include <QDebug>
#include <QFileDialog>
#include <QFileInfo>
#include <QJsonArray>

#include <sstream>

namespace {
bool hasData(vtkSMProxy* reader)
{
  vtkSMSourceProxy* dataSource = vtkSMSourceProxy::SafeDownCast(reader);
  if (!dataSource) {
    return false;
  }

  dataSource->UpdatePipeline();
  vtkAlgorithm* vtkalgorithm =
    vtkAlgorithm::SafeDownCast(dataSource->GetClientSideObject());
  if (!vtkalgorithm) {
    return false;
  }

  // Create a clone and release the reader data.
  vtkImageData* data =
    vtkImageData::SafeDownCast(vtkalgorithm->GetOutputDataObject(0));
  if (!data) {
    return false;
  }

  int extent[6];
  data->GetExtent(extent);
  if (extent[0] > extent[1] || extent[2] > extent[3] || extent[4] > extent[5]) {
    return false;
  }

  vtkPointData* pd = data->GetPointData();
  if (!pd) {
    return false;
  }

  if (pd->GetNumberOfArrays() < 1) {
    return false;
  }
  return true;
}
}

namespace tomviz {

LoadDataReaction::LoadDataReaction(QAction* parentObject)
  : pqReaction(parentObject)
{
}

LoadDataReaction::~LoadDataReaction() = default;

void LoadDataReaction::onTriggered()
{
  loadData();
}

QList<DataSource*> LoadDataReaction::loadData()
{
  QStringList filters;
  filters
    << "Common file types (*.emd *.jpg *.jpeg *.png *.tiff *.tif *.raw"
       " *.dat *.bin *.txt *.mhd *.mha *.vti *.mrc *.st *.rec *.ali *.xmf *.xdmf)"
    << "EMD (*.emd)"
    << "JPeg Image files (*.jpg *.jpeg)"
    << "PNG Image files (*.png)"
    << "TIFF Image files (*.tiff *.tif)"
    << "OME-TIFF Image files (*.ome.tif)"
    << "Raw data files (*.raw *.dat *.bin)"
    << "Meta Image files (*.mhd *.mha)"
    << "VTK ImageData Files (*.vti)"
    << "MRC files (*.mrc *.st *.rec *.ali)"
    << "XDMF files (*.xmf *.xdmf)"
    << "Text files (*.txt)"
    << "All files (*.*)";

  QFileDialog dialog(nullptr);
  dialog.setFileMode(QFileDialog::ExistingFiles);
  dialog.setNameFilters(filters);
  dialog.setObjectName("FileOpenDialog-tomviz"); // avoid name collision?

  QList<DataSource*> dataSources;
  if (dialog.exec()) {
    QStringList filenames = dialog.selectedFiles();
    dataSources << loadData(filenames);
  }

  return dataSources;
}

DataSource* LoadDataReaction::loadData(const QString& fileName,
                                       bool defaultModules, bool addToRecent,
                                       bool child, const QJsonObject& options)
{
  QJsonObject opts = options;
  opts["defaultModules"] = defaultModules;
  opts["addToRecent"] = addToRecent;
  opts["child"] = child;
  return LoadDataReaction::loadData(fileName, opts);
}

DataSource* LoadDataReaction::loadData(const QString& fileName,
                                       const QJsonObject& val)
{
  QStringList fileNames;
  fileNames << fileName;

  return loadData(fileNames, val);
}

DataSource* LoadDataReaction::loadData(const QStringList& fileNames,
                                       const QJsonObject& options)
{
  bool defaultModules = options["defaultModules"].toBool(true);
  bool addToRecent = options["addToRecent"].toBool(true);
  bool child = options["child"].toBool(false);

  DataSource* dataSource(nullptr);
  QString firstFile;
  if (fileNames.size() > 0) {
    firstFile = fileNames[0];
  }
  QFileInfo info(firstFile);
  if (info.suffix().toLower() == "emd") {
    // Load the file using our simple EMD class.
    EmdFormat emdFile;
    vtkNew<vtkImageData> imageData;
    if (emdFile.read(firstFile.toLatin1().data(), imageData)) {
      dataSource = new DataSource(imageData);
      LoadDataReaction::dataSourceAdded(dataSource, defaultModules, child);
    }
  } else if (info.completeSuffix().endsWith("ome.tif")) {
    auto pxm = tomviz::ActiveObjects::instance().proxyManager();
    const char* name = "OMETIFFReader";
    vtkSmartPointer<vtkSMProxy> source;
    source.TakeReference(pxm->NewProxy("sources", name));
    QString pname = vtkSMCoreUtilities::GetFileNameProperty(source);
    vtkSMStringVectorProperty* prop = vtkSMStringVectorProperty::SafeDownCast(
      source->GetProperty(pname.toUtf8().data()));
    pqSMAdaptor::setElementProperty(prop, firstFile);
    source->UpdateVTKObjects();

    dataSource = createDataSource(source, defaultModules, child);
    QJsonObject readerProperties;
    readerProperties["name"] = name;
    dataSource->setReaderProperties(readerProperties.toVariantMap());
  } else if (options.contains("reader")) {
    // Create the ParaView reader and set its properties using the JSON
    // configuration.
    auto props = options["reader"].toObject();
    auto name = props["name"].toString();

    auto pxm = ActiveObjects::instance().proxyManager();
    vtkSmartPointer<vtkSMProxy> reader;
    reader.TakeReference(pxm->NewProxy("sources", name.toLatin1().data()));

    setProperties(props, reader);
    setFileNameProperties(props, reader);
    reader->UpdateVTKObjects();
    vtkSMSourceProxy::SafeDownCast(reader)->UpdatePipelineInformation();
    dataSource =
      LoadDataReaction::createDataSource(reader, defaultModules, child);
    if (dataSource == nullptr) {
      return nullptr;
    }

    dataSource->setReaderProperties(props.toVariantMap());

  } else {
    // Use ParaView's file load infrastructure.
    pqPipelineSource* reader = pqLoadDataReaction::loadData(fileNames);
    if (!reader) {
      return nullptr;
    }

    dataSource = createDataSource(reader->getProxy(), defaultModules, child);
    if (dataSource == nullptr) {
      return nullptr;
    }

    QJsonObject props = readerProperties(reader->getProxy());
    props["name"] = reader->getProxy()->GetXMLName();

    dataSource->setReaderProperties(props.toVariantMap());

    vtkNew<vtkSMParaViewPipelineController> controller;
    controller->UnRegisterProxy(reader->getProxy());
  }

  // It is possible that the dataSource will be null if, for example, loading
  // a VTI is cancelled in the array selection dialog. Guard against this.
  if (!dataSource) {
    return nullptr;
  }

  // Now for house keeping, registering elements, etc.
  // always save it as a list, even if there is only one file.
  dataSource->setFileNames(fileNames);

  if (addToRecent && dataSource) {
    RecentFilesMenu::pushDataReader(dataSource);
  }
  return dataSource;
}

DataSource* LoadDataReaction::createDataSource(vtkSMProxy* reader,
                                               bool defaultModules, bool child)
{
  // Prompt user for reader configuration, unless it is TIFF.
  QScopedPointer<QDialog> dialog(new pqProxyWidgetDialog(reader));
  bool hasVisibleWidgets =
    qobject_cast<pqProxyWidgetDialog*>(dialog.data())->hasVisibleWidgets();
  if (QString(reader->GetXMLName()) == "TVRawImageReader") {
    dialog.reset(new RAWFileReaderDialog(reader));
    hasVisibleWidgets = true;
    // This will show only a partial filename when reading multiple files as a
    // raw image
    vtkSMPropertyHelper fname(reader, "FilePrefix");
    QFileInfo info(fname.GetAsString());
    dialog->setWindowTitle(QString("Opening %1").arg(info.fileName()));
  } else {
    dialog->setWindowTitle("Configure Reader Parameters");
  }
  dialog->setObjectName("ConfigureReaderDialog");
  if (QString(reader->GetXMLName()) == "TIFFSeriesReader" ||
      hasVisibleWidgets == false || dialog->exec() == QDialog::Accepted) {

    if (!hasData(reader)) {
      qCritical() << "Error: failed to load file!";
      return nullptr;
    }

    auto source = vtkSMSourceProxy::SafeDownCast(reader);
    source->UpdatePipeline();
    auto algo = vtkAlgorithm::SafeDownCast(source->GetClientSideObject());
    auto data = algo->GetOutputDataObject(0);
    auto image = vtkImageData::SafeDownCast(data);

    DataSource* dataSource = new DataSource(image);
    // Do whatever we need to do with a new data source.
    LoadDataReaction::dataSourceAdded(dataSource, defaultModules, child);
    return dataSource;
  }
  return nullptr;
}

void LoadDataReaction::dataSourceAdded(DataSource* dataSource,
                                       bool defaultModules, bool child)
{
  if (!dataSource) {
    return;
  }
  DataSource* previousActiveDataSource =
    ActiveObjects::instance().activeDataSource();
  bool oldMoveObjectsEnabled = ActiveObjects::instance().moveObjectsEnabled();
  ActiveObjects::instance().setMoveObjectsMode(false);
  if (child) {
    ModuleManager::instance().addChildDataSource(dataSource);
  } else {
    auto pipeline = new Pipeline(dataSource);
    PipelineManager::instance().addPipeline(pipeline);
    // TODO Eventually we shouldn't need to keep track of the data sources,
    // the pipeline should do that for us.
    ModuleManager::instance().addDataSource(dataSource);
    if (defaultModules) {
      pipeline->addDefaultModules(dataSource);
    }
  }

  // Work through pathological cases as necessary, prefer active view.
  ActiveObjects::instance().createRenderViewIfNeeded();
  auto view = ActiveObjects::instance().activeView();

  if (!view || QString(view->GetXMLName()) != "RenderView") {
    ActiveObjects::instance().setActiveViewToFirstRenderView();
    view = ActiveObjects::instance().activeView();
  }

  ActiveObjects::instance().setMoveObjectsMode(oldMoveObjectsEnabled);
  if (!previousActiveDataSource) {
    pqRenderView* renderView =
      qobject_cast<pqRenderView*>(pqActiveObjects::instance().activeView());
    if (renderView) {
      tomviz::createCameraOrbit(dataSource->proxy(),
                                renderView->getRenderViewProxy());
    }
  }
}

QJsonObject LoadDataReaction::readerProperties(vtkSMProxy* reader)
{
  QStringList propNames({ "DataScalarType", "DataByteOrder",
                          "NumberOfScalarComponents", "DataExtent" });

  QJsonObject props;
  foreach (QString propName, propNames) {
    auto prop = reader->GetProperty(propName.toLatin1().data());
    if (prop != nullptr) {
      props[propName] = toJson(prop);
    }
  }

  // Special case file name related properties
  auto prop = reader->GetProperty("FileName");
  if (prop != nullptr) {
    props["fileName"] = toJson(prop);
  }
  prop = reader->GetProperty("FileNames");
  if (prop != nullptr) {
    auto fileNames = toJson(prop).toArray();
    if (fileNames.size() > 1) {
      props["fileNames"] = fileNames;
    }
    // Normalize to fileNames for single value.
    else {
      props["fileName"] = fileNames[0];
    }
  }
  prop = reader->GetProperty("FilePrefix");
  if (prop != nullptr) {
    props["fileName"] = toJson(prop);
  }

  return props;
}

void LoadDataReaction::setFileNameProperties(const QJsonObject& props,
                                             vtkSMProxy* reader)
{
  auto prop = reader->GetProperty("FileName");
  if (prop != nullptr) {
    if (!props.contains("fileName")) {
      qCritical() << "Reader doesn't have 'fileName' property.";
      return;
    }
    tomviz::setProperty(props["fileName"], prop);
  }
  prop = reader->GetProperty("FileNames");
  if (prop != nullptr) {
    if (!props.contains("fileNames") && !props.contains("fileName")) {
      qCritical() << "Reader doesn't have 'fileName' or 'fileNames' property.";
      return;
    }

    if (props.contains("fileNames")) {
      tomviz::setProperty(props["fileNames"], prop);
    } else {
      QJsonArray fileNames;
      fileNames.append(props["fileName"]);
      tomviz::setProperty(fileNames, prop);
    }
  }
  prop = reader->GetProperty("FilePrefix");
  if (prop != nullptr) {
    if (!props.contains("fileName")) {
      qCritical() << "Reader doesn't have 'fileName' property.";
      return;
    }
    tomviz::setProperty(props["fileName"], prop);
  }
}

} // end of namespace tomviz
<|endoftext|>


<commit_before>//===- bugpoint.cpp - The LLVM Bugpoint utility ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This program is an automated compiler debugger tool.  It is used to narrow
// down miscompilations and crash problems to a specific pass in the compiler,
// and the specific Module or Function input that is causing the problem.
//
//===----------------------------------------------------------------------===//

#include "BugDriver.h"
#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/ToolRunner.h"
#include "llvm/System/SysConfig.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/System/Signals.h"
using namespace llvm;

static cl::list<std::string>
InputFilenames(cl::Positional, cl::OneOrMore,
               cl::desc("<input llvm ll/bc files>"));

// The AnalysesList is automatically populated with registered Passes by the
// PassNameParser.
//
static cl::list<const PassInfo*, bool, PassNameParser>
PassList(cl::desc("Passes available:"), cl::ZeroOrMore);

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv,
                              " LLVM automatic testcase reducer. See\nhttp://"
                              "llvm.cs.uiuc.edu/docs/CommandGuide/bugpoint.html"
                              " for more information.\n");
  sys::PrintStackTraceOnErrorSignal();

  BugDriver D(argv[0]);
  if (D.addSources(InputFilenames)) return 1;
  D.addPasses(PassList.begin(), PassList.end());

  // Bugpoint has the ability of generating a plethora of core files, so to
  // avoid filling up the disk, we prevent it
  sys::PreventCoreFiles();

  try {
    return D.run();
  } catch (ToolExecutionError &TEE) {
    std::cerr << "Tool execution error: " << TEE.what() << '\n';
    return 1;
  } catch (...) {
    std::cerr << "Whoops, an exception leaked out of bugpoint.  "
              << "This is a bug in bugpoint!\n";
    return 1;
  }
}
<commit_msg>For PR351: * sys::PreventCoreFiles -> sys::Process::PreventCoreFiles<commit_after>//===- bugpoint.cpp - The LLVM Bugpoint utility ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This program is an automated compiler debugger tool.  It is used to narrow
// down miscompilations and crash problems to a specific pass in the compiler,
// and the specific Module or Function input that is causing the problem.
//
//===----------------------------------------------------------------------===//

#include "BugDriver.h"
#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/ToolRunner.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/System/Process.h"
#include "llvm/System/Signals.h"
using namespace llvm;

static cl::list<std::string>
InputFilenames(cl::Positional, cl::OneOrMore,
               cl::desc("<input llvm ll/bc files>"));

// The AnalysesList is automatically populated with registered Passes by the
// PassNameParser.
//
static cl::list<const PassInfo*, bool, PassNameParser>
PassList(cl::desc("Passes available:"), cl::ZeroOrMore);

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv,
                              " LLVM automatic testcase reducer. See\nhttp://"
                              "llvm.cs.uiuc.edu/docs/CommandGuide/bugpoint.html"
                              " for more information.\n");
  sys::PrintStackTraceOnErrorSignal();

  BugDriver D(argv[0]);
  if (D.addSources(InputFilenames)) return 1;
  D.addPasses(PassList.begin(), PassList.end());

  // Bugpoint has the ability of generating a plethora of core files, so to
  // avoid filling up the disk, we prevent it
  sys::Process::PreventCoreFiles();

  try {
    return D.run();
  } catch (ToolExecutionError &TEE) {
    std::cerr << "Tool execution error: " << TEE.what() << '\n';
    return 1;
  } catch (...) {
    std::cerr << "Whoops, an exception leaked out of bugpoint.  "
              << "This is a bug in bugpoint!\n";
    return 1;
  }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <unistd.h>
#include <vector>
#include <atomic>
#include <signal.h>

#include <getopt.h>

#include "zcm/zcm-cpp.hpp"

using namespace std;

static atomic_int done {0};

static void sighandler(int signal)
{
    done++;
    if (done == 3) exit(1);
}

struct Args
{
    vector<string> Achannels;
    vector<string> Bchannels;

    string Aurl = "";
    string Burl = "";

    bool parse(int argc, char *argv[])
    {
        // set some defaults
        const char *optstring = "hA:B:a:b:";
        struct option long_opts[] = {
            { "help", no_argument, 0, 'h' },
            { "A-endpt", required_argument, 0, 'A'},
            { "B-endpt", required_argument, 0, 'B'},
            { "A-channel", required_argument, 0, 'a' },
            { "B-channel", required_argument, 0, 'b' },
            { 0, 0, 0, 0 }
        };

        int c;
        while ((c = getopt_long (argc, argv, optstring, long_opts, 0)) >= 0) {
            switch (c) {
                case 'A':
                    Aurl = optarg;
                    break;
                case 'B':
                    Burl = optarg;
                    break;
                case 'a':
                    Achannels.push_back(optarg);
                    break;
                case 'b':
                    Bchannels.push_back(optarg);
                    break;
                case 'h':
                default:
                    return false;
            };
        }

        if (Aurl == "") {
            cerr << "Please specify A endpt url with the -A option" << endl;
            return false;
        }

        if (Burl == "") {
            cerr << "Please specify B endpt url with the -B option" << endl;
            return false;
        }

        if (Aurl == Burl) {
            cerr << "A and B endpoint urls must be unique" << endl;
            return false;
        }

        return true;
    }
};

struct Bridge
{
    Args   args;

    zcm::ZCM *zcmA = nullptr;
    zcm::ZCM *zcmB = nullptr;

    Bridge() {}

    ~Bridge()
    {
        if (zcmA)
            delete zcmA;
        if (zcmB)
            delete zcmB;
    }

    bool init(int argc, char *argv[])
    {
        if (!args.parse(argc, argv))
            return false;

        // A endpoint network
        zcmA = new zcm::ZCM(args.Aurl);
        if (!zcmA->good()) {
            cerr << "Couldn't initialize A endpoint ZCM network! "
                    "Please check your A endpoint transport url." << endl << endl;
            delete zcmA;
            zcmA = nullptr;
            return false;
        }

        // B endpoint network
        zcmB = new zcm::ZCM(args.Burl);
        if (!zcmB->good()) {
            cerr << "Couldn't initialize B endpoint ZCM network! "
                    "Please check your B endpoint transport url." << endl << endl;
            delete zcmB;
            zcmB = nullptr;
            return false;
        }

        return true;
    }

    static void handler(const zcm::ReceiveBuffer* rbuf, const string& channel, void* usr)
    {
        ((zcm::ZCM*)usr)->publish(channel, rbuf->data, rbuf->data_size);
    }

    void run()
    {
        if (args.Achannels.size() == 0) {
            zcmA->subscribe(".*", &handler, zcmB);
        } else {
            for (auto iter : args.Achannels)
                zcmA->subscribe(iter, &handler, zcmB);
        }

        if (args.Bchannels.size() == 0) {
            zcmB->subscribe(".*", &handler, zcmA);
        } else {
            for (auto iter : args.Bchannels)
                zcmB->subscribe(iter, &handler, zcmA);
        }

        zcmA->start();
        zcmB->start();

        while (!done) usleep(1e6);

        zcmA->stop();
        zcmB->stop();

        zcmA->flush();
        zcmB->flush();
    }
};

static void usage()
{
    cerr << "usage: zcm-bridge [options]" << endl
         << "" << endl
         << "    ZCM bridge utility. Bridges all data from one ZCM network to another." << endl
         << "" << endl
         << "Example:" << endl
         << "    zcm-bridge -A ipc -B udpm://239.255.76.67:7667?ttl=0" << endl
         << "" << endl
         << "Options:" << endl
         << "" << endl
         << "  -h, --help                 Shows this help text and exits" << endl
         << "  -A, --A-enpt=URL           One end of the bridge. Ex: zcm-bridge -A ipc" << endl
         << "  -B, --B-endpt=URL          One end of the bridge. Ex: zcm-bridge -B udpm://239.255.76.67:7667?ttl=0" << endl
         << "  -a, --A-channel=CHANNEL    One channel to subscribe to on A and repeat to B." << endl
         << "                             This argument can be specified multiple times. If this option is not," << endl
         << "                             present then we subscribe to all messages on the A interface." << endl
         << "                             Ex: zcm-bridge -A ipc -a EXAMPLE -B udpm://239.255.76.67:7667?ttl=0" << endl
         << "  -b, --B-channel=CHANNEL    One channel to subscribe to on B and repeat to A." << endl
         << "                             This argument can be specified multiple times. If this option is not," << endl
         << "                             present then we subscribe to all messages on the B interface." << endl
         << "                             Ex: zcm-bridge -A ipc -B udpm://239.255.76.67:7667?ttl=0 -b EXAMPLE" << endl
         << "" << endl << endl;
}

int main(int argc, char *argv[])
{
    Bridge bridge{};
    if (!bridge.init(argc, argv)) {
        usage();
        return 1;
    }

    // Register signal handlers
    signal(SIGINT, sighandler);
    signal(SIGQUIT, sighandler);
    signal(SIGTERM, sighandler);

    bridge.run();

    cerr << "Bridge exiting" << endl;

    return 0;
}
<commit_msg>A little cleanup in bridge<commit_after>#include <iostream>
#include <string>
#include <unistd.h>
#include <vector>
#include <atomic>
#include <signal.h>

#include <getopt.h>

#include "zcm/zcm-cpp.hpp"

using namespace std;

static atomic_int done {0};

static void sighandler(int signal)
{
    done++;
    if (done == 3) exit(1);
}

struct Args
{
    vector<string> Achannels;
    vector<string> Bchannels;

    string Aurl = "";
    string Burl = "";

    bool parse(int argc, char *argv[])
    {
        // set some defaults
        const char *optstring = "hA:B:a:b:";
        struct option long_opts[] = {
            { "help", no_argument, 0, 'h' },
            { "A-endpt", required_argument, 0, 'A'},
            { "B-endpt", required_argument, 0, 'B'},
            { "A-channel", required_argument, 0, 'a' },
            { "B-channel", required_argument, 0, 'b' },
            { 0, 0, 0, 0 }
        };

        int c;
        while ((c = getopt_long (argc, argv, optstring, long_opts, 0)) >= 0) {
            switch (c) {
                case 'A': Aurl = optarg; break;
                case 'B': Burl = optarg; break;
                case 'a': Achannels.push_back(optarg); break;
                case 'b': Bchannels.push_back(optarg); break;
                case 'h': default: return false;
            };
        }

        if (Aurl == "") {
            cerr << "Please specify A endpt url with the -A option" << endl;
            return false;
        }

        if (Burl == "") {
            cerr << "Please specify B endpt url with the -B option" << endl;
            return false;
        }

        if (Aurl == Burl) {
            cerr << "A and B endpoint urls must be unique" << endl;
            return false;
        }

        return true;
    }
};

struct Bridge
{
    Args   args;

    zcm::ZCM *zcmA = nullptr;
    zcm::ZCM *zcmB = nullptr;

    Bridge() {}

    ~Bridge()
    {
        if (zcmA) delete zcmA;
        if (zcmB) delete zcmB;
    }

    bool init(int argc, char *argv[])
    {
        if (!args.parse(argc, argv))
            return false;

        // A endpoint network
        zcmA = new zcm::ZCM(args.Aurl);
        if (!zcmA->good()) {
            cerr << "Couldn't initialize A endpoint ZCM network! "
                    "Please check your A endpoint transport url." << endl << endl;
            delete zcmA;
            zcmA = nullptr;
            return false;
        }

        // B endpoint network
        zcmB = new zcm::ZCM(args.Burl);
        if (!zcmB->good()) {
            cerr << "Couldn't initialize B endpoint ZCM network! "
                    "Please check your B endpoint transport url." << endl << endl;
            delete zcmB;
            zcmB = nullptr;
            return false;
        }

        return true;
    }

    static void handler(const zcm::ReceiveBuffer* rbuf, const string& channel, void* usr)
    {
        ((zcm::ZCM*)usr)->publish(channel, rbuf->data, rbuf->data_size);
    }

    void run()
    {
        if (args.Achannels.size() == 0) {
            zcmA->subscribe(".*", &handler, zcmB);
        } else {
            for (auto iter : args.Achannels)
                zcmA->subscribe(iter, &handler, zcmB);
        }

        if (args.Bchannels.size() == 0) {
            zcmB->subscribe(".*", &handler, zcmA);
        } else {
            for (auto iter : args.Bchannels)
                zcmB->subscribe(iter, &handler, zcmA);
        }

        zcmA->start();
        zcmB->start();

        while (!done) usleep(1e6);

        zcmA->stop();
        zcmB->stop();

        zcmA->flush();
        zcmB->flush();
    }
};

static void usage()
{
    cerr << "usage: zcm-bridge [options]" << endl
         << "" << endl
         << "    ZCM bridge utility. Bridges all data from one ZCM network to another." << endl
         << "" << endl
         << "Example:" << endl
         << "    zcm-bridge -A ipc -B udpm://239.255.76.67:7667?ttl=0" << endl
         << "" << endl
         << "Options:" << endl
         << "" << endl
         << "  -h, --help                 Shows this help text and exits" << endl
         << "  -A, --A-enpt=URL           One end of the bridge. Ex: zcm-bridge -A ipc" << endl
         << "  -B, --B-endpt=URL          One end of the bridge. Ex: zcm-bridge -B udpm://239.255.76.67:7667?ttl=0" << endl
         << "  -a, --A-channel=CHANNEL    One channel to subscribe to on A and repeat to B." << endl
         << "                             This argument can be specified multiple times. If this option is not," << endl
         << "                             present then we subscribe to all messages on the A interface." << endl
         << "                             Ex: zcm-bridge -A ipc -a EXAMPLE -B udpm://239.255.76.67:7667?ttl=0" << endl
         << "  -b, --B-channel=CHANNEL    One channel to subscribe to on B and repeat to A." << endl
         << "                             This argument can be specified multiple times. If this option is not," << endl
         << "                             present then we subscribe to all messages on the B interface." << endl
         << "                             Ex: zcm-bridge -A ipc -B udpm://239.255.76.67:7667?ttl=0 -b EXAMPLE" << endl
         << "" << endl << endl;
}

int main(int argc, char *argv[])
{
    Bridge bridge{};
    if (!bridge.init(argc, argv)) {
        usage();
        return 1;
    }

    // Register signal handlers
    signal(SIGINT, sighandler);
    signal(SIGQUIT, sighandler);
    signal(SIGTERM, sighandler);

    bridge.run();

    cerr << "Bridge exiting" << endl;

    return 0;
}
<|endoftext|>


<commit_before>//
//  nn_example.cpp
//
//  Created by Manuel Blum on 21.02.13.
//  Copyright (c) 2012 Uni Freiburg. All rights reserved.
//

#include <Eigen/Dense>
#include <iostream>

#include "nn.h"

int main (int argc, const char* argv[]) {

  // input dimensionality
  int n_input = 2;
  // output dimensionality
  int n_output = 1;
  // number of training samples
  int m = 4;
  // number of layers
  int k = 3;
  // number of optimization steps
  int max_steps = 50;
  // regularization parameter
  int lambda = 0.01;

  // training inputs
  matrix_t X(m, n_input);
  matrix_t Y(m, n_output);

  // XOR problem
  X << 0, 0, 0, 1, 1, 0, 1, 1;
  Y << 0, 1, 1, 0;
  std::cout << "training input: " << std::endl << X << std::endl;
  std::cout << "training output: " << std::endl << Y << std::endl;

  // specify network topology
  Eigen::VectorXi topo(k);
  topo << n_input, 5, n_output;
  std::cout << "topology: " << std::endl << topo << std::endl;

  // initialize a neural network with given topology
  NeuralNet nn(topo);

  // train the network
  std::cout << "starting training" << std::endl;
  double err;
  for (int i = 0; i < max_steps; ++i) {
    err = nn.loss(X, Y, lambda);
    nn.rprop();
    printf("%3i   %4.4f\n", i, err*err);
  }

  // write model to disk
  nn.write("example.net");

  // read model from disk
  NeuralNet nn2("example.net");

  // testing
  nn2.forward_pass(X);
  matrix_t Y_test = nn2.layer.back().a;

  std::cout << "test input:" << std::endl << X << std::endl;
  std::cout << "test output:" << std::endl << Y_test << std::endl;

  return 0;
}

<commit_msg>adding headers for printf<commit_after>//
//  nn_example.cpp
//
//  Created by Manuel Blum on 21.02.13.
//  Copyright (c) 2012 Uni Freiburg. All rights reserved.
//

#include <Eigen/Dense>
#include <iostream>
#include <cstdio>

#include "nn.h"

int main (int argc, const char* argv[]) {

  // input dimensionality
  int n_input = 2;
  // output dimensionality
  int n_output = 1;
  // number of training samples
  int m = 4;
  // number of layers
  int k = 3;
  // number of optimization steps
  int max_steps = 50;
  // regularization parameter
  int lambda = 0.01;

  // training inputs
  matrix_t X(m, n_input);
  matrix_t Y(m, n_output);

  // XOR problem
  X << 0, 0, 0, 1, 1, 0, 1, 1;
  Y << 0, 1, 1, 0;
  std::cout << "training input: " << std::endl << X << std::endl;
  std::cout << "training output: " << std::endl << Y << std::endl;

  // specify network topology
  Eigen::VectorXi topo(k);
  topo << n_input, 5, n_output;
  std::cout << "topology: " << std::endl << topo << std::endl;

  // initialize a neural network with given topology
  NeuralNet nn(topo);

  // train the network
  std::cout << "starting training" << std::endl;
  double err;
  for (int i = 0; i < max_steps; ++i) {
    err = nn.loss(X, Y, lambda);
    nn.rprop();
    printf("%3i   %4.4f\n", i, err*err);
  }

  // write model to disk
  nn.write("example.net");

  // read model from disk
  NeuralNet nn2("example.net");

  // testing
  nn2.forward_pass(X);
  matrix_t Y_test = nn2.layer.back().a;

  std::cout << "test input:" << std::endl << X << std::endl;
  std::cout << "test output:" << std::endl << Y_test << std::endl;

  return 0;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: fltrcfg.hxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _SVT_FLTRCFG_HXX
#define _SVT_FLTRCFG_HXX

// -----------------------------------------------------------------------

#include "svtools/svldllapi.h"
#include <unotools/configitem.hxx>

struct SvtFilterOptions_Impl;
class SVL_DLLPUBLIC SvtFilterOptions : public utl::ConfigItem
{
    SvtFilterOptions_Impl* pImp;

    const com::sun::star::uno::Sequence<rtl::OUString>& GetPropertyNames();
public:
                    SvtFilterOptions();
    virtual        ~SvtFilterOptions();

    virtual void            Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames);
    virtual void            Commit();
    void                    Load();

    void SetLoadWordBasicCode( sal_Bool bFlag );
    sal_Bool IsLoadWordBasicCode() const;
    void SetLoadWordBasicStorage( sal_Bool bFlag );
    sal_Bool IsLoadWordBasicStorage() const;

    void SetLoadExcelBasicCode( sal_Bool bFlag );
    sal_Bool IsLoadExcelBasicCode() const;
    void SetLoadExcelBasicExecutable( sal_Bool bFlag );
    sal_Bool IsLoadExcelBasicExecutable() const;
    void SetLoadExcelBasicStorage( sal_Bool bFlag );
    sal_Bool IsLoadExcelBasicStorage() const;

    void SetLoadPPointBasicCode( sal_Bool bFlag );
    sal_Bool IsLoadPPointBasicCode() const;
    void SetLoadPPointBasicStorage( sal_Bool bFlag );
    sal_Bool IsLoadPPointBasicStorage() const;

    sal_Bool IsMathType2Math() const;
    void SetMathType2Math( sal_Bool bFlag );
    sal_Bool IsMath2MathType() const;
    void SetMath2MathType( sal_Bool bFlag );

    sal_Bool IsWinWord2Writer() const;
    void SetWinWord2Writer( sal_Bool bFlag );
    sal_Bool IsWriter2WinWord() const;
    void SetWriter2WinWord( sal_Bool bFlag );

    sal_Bool IsExcel2Calc() const;
    void SetExcel2Calc( sal_Bool bFlag );
    sal_Bool IsCalc2Excel() const;
    void SetCalc2Excel( sal_Bool bFlag );

    sal_Bool IsPowerPoint2Impress() const;
    void SetPowerPoint2Impress( sal_Bool bFlag );
    sal_Bool IsImpress2PowerPoint() const;
    void SetImpress2PowerPoint( sal_Bool bFlag );

    static SvtFilterOptions* Get();
};

#endif

<commit_msg>INTEGRATION: CWS impress141 (1.5.680); FILE MERGED 2008/04/21 09:20:48 cl 1.5.680.2: RESYNC: (1.5-1.6); FILE MERGED 2008/04/15 14:50:43 sj 1.5.680.1: #i67371# added possibility to disable/enable previews when exporting to ppt,excel and or word<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: fltrcfg.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _SVT_FLTRCFG_HXX
#define _SVT_FLTRCFG_HXX

// -----------------------------------------------------------------------

#include "svtools/svldllapi.h"
#include <unotools/configitem.hxx>

struct SvtFilterOptions_Impl;
class SVL_DLLPUBLIC SvtFilterOptions : public utl::ConfigItem
{
    SvtFilterOptions_Impl* pImp;

    const com::sun::star::uno::Sequence<rtl::OUString>& GetPropertyNames();
public:
                    SvtFilterOptions();
    virtual        ~SvtFilterOptions();

    virtual void            Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames);
    virtual void            Commit();
    void                    Load();

    void SetLoadWordBasicCode( sal_Bool bFlag );
    sal_Bool IsLoadWordBasicCode() const;
    void SetLoadWordBasicStorage( sal_Bool bFlag );
    sal_Bool IsLoadWordBasicStorage() const;

    void SetLoadExcelBasicCode( sal_Bool bFlag );
    sal_Bool IsLoadExcelBasicCode() const;
    void SetLoadExcelBasicExecutable( sal_Bool bFlag );
    sal_Bool IsLoadExcelBasicExecutable() const;
    void SetLoadExcelBasicStorage( sal_Bool bFlag );
    sal_Bool IsLoadExcelBasicStorage() const;

    void SetLoadPPointBasicCode( sal_Bool bFlag );
    sal_Bool IsLoadPPointBasicCode() const;
    void SetLoadPPointBasicStorage( sal_Bool bFlag );
    sal_Bool IsLoadPPointBasicStorage() const;

    sal_Bool IsMathType2Math() const;
    void SetMathType2Math( sal_Bool bFlag );
    sal_Bool IsMath2MathType() const;
    void SetMath2MathType( sal_Bool bFlag );

    sal_Bool IsWinWord2Writer() const;
    void SetWinWord2Writer( sal_Bool bFlag );
    sal_Bool IsWriter2WinWord() const;
    void SetWriter2WinWord( sal_Bool bFlag );

    sal_Bool IsExcel2Calc() const;
    void SetExcel2Calc( sal_Bool bFlag );
    sal_Bool IsCalc2Excel() const;
    void SetCalc2Excel( sal_Bool bFlag );

    sal_Bool IsPowerPoint2Impress() const;
    void SetPowerPoint2Impress( sal_Bool bFlag );
    sal_Bool IsImpress2PowerPoint() const;
    void SetImpress2PowerPoint( sal_Bool bFlag );

    sal_Bool IsEnablePPTPreview() const;
    sal_Bool IsEnableCalcPreview() const;
    sal_Bool IsEnableWordPreview() const;

    static SvtFilterOptions* Get();
};

#endif

<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "mediasource.h"
#include "mediasource_p.h"
#include "iodevicestream.h"
#include <QFile>

namespace Phonon
{

MediaSource::MediaSource()
    : d(new MediaSourcePrivate(Invalid))
{
}

MediaSource::MediaSource(const QString &filename)
    : d(new MediaSourcePrivate(LocalFile))
{
    if (filename.size() > 0 && filename.startsWith(QLatin1Char(':'))) {
        // it's a Qt resource -> use QFile
        d->type = Stream;
        d->resourceFile = new QFile(filename);
        d->stream = new IODeviceStream(d->resourceFile, d->resourceFile);
    } else {
        d->url = QUrl::fromLocalFile(filename);
    }
}

MediaSource::MediaSource(const QUrl &url)
    : d(new MediaSourcePrivate(Url))
{
    d->url = url;
}

MediaSource::MediaSource(Phonon::DiscType dt, const QString &deviceName)
    : d(new MediaSourcePrivate(Disc))
{
    d->discType = dt;
    d->deviceName = deviceName;
}

MediaSource::MediaSource(AbstractMediaStream *stream)
    : d(new MediaSourcePrivate(Stream))
{
    d->stream = stream;
}

MediaSource::MediaSource(QIODevice *ioDevice)
    : d(new MediaSourcePrivate(Stream))
{
    d->stream = new IODeviceStream(ioDevice, ioDevice);
}

MediaSource::~MediaSource()
{
    delete d->resourceFile;
    d->resourceFile = 0;
}

MediaSource::MediaSource(const MediaSource &rhs)
    : d(rhs.d)
{
}

MediaSource &MediaSource::operator=(const MediaSource &rhs)
{
    d = rhs.d;
    return *this;
}

bool MediaSource::operator==(const MediaSource &rhs) const
{
    return d == rhs.d;
}

MediaSource::Type MediaSource::type() const
{
    if (d->type == Stream && d->stream == 0) {
        return Invalid;
    }
    return d->type;
}

QString MediaSource::filename() const
{
    return d->url.toLocalFile();
}

QUrl MediaSource::url() const
{
    return d->url;
}

Phonon::DiscType MediaSource::discType() const
{
    return d->discType;
}

QString MediaSource::deviceName() const
{
    return d->deviceName;
}

AbstractMediaStream *MediaSource::stream() const
{
    return d->stream;
}

//X AudioCaptureDevice MediaSource::audioCaptureDevice() const
//X {
//X     return d->audioCaptureDevice;
//X }
//X
//X VideoCaptureDevice MediaSource::videoCaptureDevice() const
//X {
//X     return d->videoCaptureDevice;
//X }

} // namespace Phonon

// vim: sw=4 sts=4 et tw=100
<commit_msg>passing NoDisc makes it an invalid MediaSource<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "mediasource.h"
#include "mediasource_p.h"
#include "iodevicestream.h"
#include <QFile>

namespace Phonon
{

MediaSource::MediaSource()
    : d(new MediaSourcePrivate(Invalid))
{
}

MediaSource::MediaSource(const QString &filename)
    : d(new MediaSourcePrivate(LocalFile))
{
    if (filename.size() > 0 && filename.startsWith(QLatin1Char(':'))) {
        // it's a Qt resource -> use QFile
        d->type = Stream;
        d->resourceFile = new QFile(filename);
        d->stream = new IODeviceStream(d->resourceFile, d->resourceFile);
    } else {
        d->url = QUrl::fromLocalFile(filename);
    }
}

MediaSource::MediaSource(const QUrl &url)
    : d(new MediaSourcePrivate(Url))
{
    d->url = url;
}

MediaSource::MediaSource(Phonon::DiscType dt, const QString &deviceName)
    : d(new MediaSourcePrivate(Disc))
{
    if (dt == NoDisc) {
        d->type = Invalid;
        return;
    }
    d->discType = dt;
    d->deviceName = deviceName;
}

MediaSource::MediaSource(AbstractMediaStream *stream)
    : d(new MediaSourcePrivate(Stream))
{
    d->stream = stream;
}

MediaSource::MediaSource(QIODevice *ioDevice)
    : d(new MediaSourcePrivate(Stream))
{
    d->stream = new IODeviceStream(ioDevice, ioDevice);
}

MediaSource::~MediaSource()
{
    delete d->resourceFile;
    d->resourceFile = 0;
}

MediaSource::MediaSource(const MediaSource &rhs)
    : d(rhs.d)
{
}

MediaSource &MediaSource::operator=(const MediaSource &rhs)
{
    d = rhs.d;
    return *this;
}

bool MediaSource::operator==(const MediaSource &rhs) const
{
    return d == rhs.d;
}

MediaSource::Type MediaSource::type() const
{
    if (d->type == Stream && d->stream == 0) {
        return Invalid;
    }
    return d->type;
}

QString MediaSource::filename() const
{
    return d->url.toLocalFile();
}

QUrl MediaSource::url() const
{
    return d->url;
}

Phonon::DiscType MediaSource::discType() const
{
    return d->discType;
}

QString MediaSource::deviceName() const
{
    return d->deviceName;
}

AbstractMediaStream *MediaSource::stream() const
{
    return d->stream;
}

//X AudioCaptureDevice MediaSource::audioCaptureDevice() const
//X {
//X     return d->audioCaptureDevice;
//X }
//X
//X VideoCaptureDevice MediaSource::videoCaptureDevice() const
//X {
//X     return d->videoCaptureDevice;
//X }

} // namespace Phonon

// vim: sw=4 sts=4 et tw=100
<|endoftext|>


<commit_before>// Copyright (C) 2015 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "Node.h"
#include "Engine.h"
#include "SceneManager.h"
#include "Layer.h"
#include "Animator.h"
#include "Camera.h"
#include "Utils.h"
#include "MathUtils.h"

namespace ouzel
{
    Node::Node()
    {

    }

    Node::~Node()
    {

    }

    void Node::draw()
    {
        if (_transformDirty)
        {
            calculateTransform();
        }
    }

    void Node::update(float delta)
    {
        if (_currentAnimator)
        {
            _currentAnimator->update(delta);
        }

        if (_transformDirty)
        {
            calculateTransform();
        }
    }

    bool Node::addChild(const NodePtr& node)
    {
        if (NodeContainer::addChild(node))
        {
            node->addToLayer(_layer);
            node->setParentVisible(_visible && _parentVisible);

            if (_transformDirty)
            {
                calculateTransform();
            }
            else
            {
                node->updateTransform(_transform);
            }

            return true;
        }
        else
        {
            return false;
        }
    }

    bool Node::removeFromParent()
    {
        if (NodeContainerPtr parent = _parent.lock())
        {
            parent->removeChild(std::static_pointer_cast<Node>(shared_from_this()));
            return true;
        }

        return false;
    }

    void Node::setZ(float z)
    {
        _z = z;

        if (LayerPtr layer = _layer.lock())
        {
            layer->reorderNodes();
        }

        markTransformDirty();
    }

    void Node::setPosition(const Vector2& position)
    {
        _position = position;

        markTransformDirty();
    }

    void Node::setRotation(float rotation)
    {
        _rotation = rotation;

        markTransformDirty();
    }

    void Node::setScale(const Vector2& scale)
    {
        _scale = scale;

        markTransformDirty();
    }

    void Node::setFlipX(bool flipX)
    {
        _flipX = flipX;

        markTransformDirty();
    }

    void Node::setFlipY(bool flipY)
    {
        _flipY = flipY;

        markTransformDirty();
    }

    void Node::setVisible(bool visible)
    {
        if (visible != _visible)
        {
            _visible = visible;

            setParentVisible(_parentVisible);
        }
    }

    void Node::addToLayer(const LayerWeakPtr& layer)
    {
        _layer = layer;

        if (LayerPtr layer = _layer.lock())
        {
            layer->addNode(std::static_pointer_cast<Node>(shared_from_this()));

            for (NodePtr child : _children)
            {
                child->addToLayer(layer);
            }
        }
    }

    void Node::removeFromLayer()
    {
        if (LayerPtr layer = _layer.lock())
        {
            layer->removeNode(std::static_pointer_cast<Node>(shared_from_this()));

            for (NodePtr child : _children)
            {
                child->removeFromLayer();
            }
        }
    }

    bool Node::pointOn(const Vector2& position) const
    {
        return _boundingBox.containPoint(convertWorldToLocal(position));
    }

    bool Node::rectangleOverlaps(const Rectangle& rectangle) const
    {
        if (_boundingBox.isEmpty())
        {
            return false;
        }

        Vector3 localLeftBottom = Vector3(rectangle.x, rectangle.y, 0.0f);

        const Matrix4& inverseTransform = getInverseTransform();
        inverseTransform.transformPoint(&localLeftBottom);

        Vector3 localRightTop =  Vector3(rectangle.x + rectangle.width, rectangle.y + rectangle.height, 0.0f);

        inverseTransform.transformPoint(&localRightTop);

        if (localLeftBottom.x > _boundingBox.max.x ||
            localLeftBottom.y > _boundingBox.max.y ||
            localRightTop.x < _boundingBox.min.x ||
            localRightTop.y < _boundingBox.min.y)
        {
            return false;
        }

        return true;
    }

    const Matrix4& Node::getTransform() const
    {
        if (_transformDirty)
        {
            calculateTransform();
        }

        return _transform;
    }

    const Matrix4& Node::getInverseTransform() const
    {
        if (_transformDirty)
        {
            calculateTransform();
        }

        if (_inverseTransformDirty)
        {
            calculateInverseTransform();
        }

        return _inverseTransform;
    }

    void Node::updateTransform(const Matrix4& parentTransform)
    {
        _parentTransform = parentTransform;
        calculateTransform();
        _inverseTransformDirty = true;
    }

    Vector2 Node::convertWorldToLocal(const Vector2& position) const
    {
        Vector3 localPosition = position;

        const Matrix4& inverseTransform = getInverseTransform();
        inverseTransform.transformPoint(&localPosition);

        return Vector2(localPosition.x, localPosition.y);
    }

    Vector2 Node::convertLocalToWorld(const Vector2& position) const
    {
        Vector3 worldPosition = position;

        const Matrix4& transform = getTransform();
        transform.transformPoint(&worldPosition);

        return Vector2(worldPosition.x, worldPosition.y);
    }

    bool Node::checkVisibility() const
    {
        if (LayerPtr layer = _layer.lock())
        {
            if (_boundingBox.isEmpty())
            {
                return true;
            }

            Matrix4 mvp = layer->getProjection() * layer->getCamera()->getTransform() * _transform;

            Vector3 corners[4] = {
                Vector3(_boundingBox.min.x, _boundingBox.min.y, 0.0f),
                Vector3(_boundingBox.max.x, _boundingBox.min.y, 0.0f),
                Vector3(_boundingBox.max.x, _boundingBox.max.y, 0.0f),
                Vector3(_boundingBox.min.x, _boundingBox.max.y, 0.0f)
            };

            uint8_t inCorners = 0;

            for (Vector3& corner : corners)
            {
                mvp.transformPoint(&corner);

                if (corner.x >= -1.0f && corner.x <= 1.0f && corner.y >= -1.0f && corner.y <= 1.0f)
                {
                    return true;
                }

                if (corner.x < -1.0f && corner.y < -1.0f) inCorners |= 0x01;
                if (corner.x > 1.0f && corner.y < -1.0f) inCorners |= 0x02;
                if (corner.x > 1.0f && corner.y > 1.0f) inCorners |= 0x04;
                if (corner.x < -1.0f && corner.y > 1.0f) inCorners |= 0x08;
            }

            // bounding box is bigger than screen
            if (inCorners == 0x0F)
            {
                return true;
            }

            for (uint32_t current = 0; current < 4; ++current)
            {
                uint32_t next = (current == 3) ? 0 : current + 1;

                if (linesIntersect(Vector2(corners[current].x, corners[current].y), Vector2(corners[next].x, corners[next].y), Vector2(-1.0f, 1.0f), Vector2(1.0f, 1.0f)) || // top
                    linesIntersect(Vector2(corners[current].x, corners[current].y), Vector2(corners[next].x, corners[next].y), Vector2(-1.0f, -1.0f), Vector2(1.0f, -1.0f)) || // bottom
                    linesIntersect(Vector2(corners[current].x, corners[current].y), Vector2(corners[next].x, corners[next].y), Vector2(1.0f, -1.0f), Vector2(1.0f, 1.0f)) || // right
                    linesIntersect(Vector2(corners[current].x, corners[current].y), Vector2(corners[next].x, corners[next].y), Vector2(-1.0f, -1.0f), Vector2(-1.0f, 1.0f))) // left
                {
                    return true;
                }
            }
        }

        return false;
    }

    void Node::animate(const AnimatorPtr& animator)
    {
        _currentAnimator = animator;

        if (_currentAnimator)
        {
            _currentAnimator->start(std::static_pointer_cast<Node>(shared_from_this()));
        }
    }

    void Node::stopAnimation()
    {
        if (_currentAnimator)
        {
            _currentAnimator->stop();
            _currentAnimator.reset();
        }
    }

    void Node::calculateTransform() const
    {
        Matrix4 translation;
        translation.translate(Vector3(_position.x, _position.y, 0.0f));

        Matrix4 rotation;
        rotation.rotate(Vector3(0.0f, 0.0f, -1.0f), _rotation);

        Vector3 realScale = Vector3(_scale.x * (_flipX ? -1.0f : 1.0f),
                                    _scale.y * (_flipY ? -1.0f : 1.0f),
                                    1.0f);

        Matrix4 scale;
        scale.scale(realScale);

        _transform = _parentTransform * translation * rotation * scale;
        _transformDirty = false;

        for (NodePtr child : _children)
        {
            child->updateTransform(_transform);
        }
    }

    void Node::calculateInverseTransform() const
    {
        if (_transformDirty)
        {
            calculateTransform();
        }

        _inverseTransform = _transform;
        _inverseTransform.invert();
        _inverseTransformDirty = false;
    }

    void Node::markTransformDirty() const
    {
        _transformDirty = true;
        _inverseTransformDirty = true;
    }

    void Node::setParentVisible(bool parentVisible)
    {
        _parentVisible = parentVisible;

        for (const NodePtr& child : _children)
        {
            child->setParentVisible(_visible && _parentVisible);
        }
    }
}
<commit_msg>Check bounding radius instead of bounding box<commit_after>// Copyright (C) 2015 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "Node.h"
#include "Engine.h"
#include "SceneManager.h"
#include "Layer.h"
#include "Animator.h"
#include "Camera.h"
#include "Utils.h"
#include "MathUtils.h"

namespace ouzel
{
    Node::Node()
    {

    }

    Node::~Node()
    {

    }

    void Node::draw()
    {
        if (_transformDirty)
        {
            calculateTransform();
        }
    }

    void Node::update(float delta)
    {
        if (_currentAnimator)
        {
            _currentAnimator->update(delta);
        }

        if (_transformDirty)
        {
            calculateTransform();
        }
    }

    bool Node::addChild(const NodePtr& node)
    {
        if (NodeContainer::addChild(node))
        {
            node->addToLayer(_layer);
            node->setParentVisible(_visible && _parentVisible);

            if (_transformDirty)
            {
                calculateTransform();
            }
            else
            {
                node->updateTransform(_transform);
            }

            return true;
        }
        else
        {
            return false;
        }
    }

    bool Node::removeFromParent()
    {
        if (NodeContainerPtr parent = _parent.lock())
        {
            parent->removeChild(std::static_pointer_cast<Node>(shared_from_this()));
            return true;
        }

        return false;
    }

    void Node::setZ(float z)
    {
        _z = z;

        if (LayerPtr layer = _layer.lock())
        {
            layer->reorderNodes();
        }

        markTransformDirty();
    }

    void Node::setPosition(const Vector2& position)
    {
        _position = position;

        markTransformDirty();
    }

    void Node::setRotation(float rotation)
    {
        _rotation = rotation;

        markTransformDirty();
    }

    void Node::setScale(const Vector2& scale)
    {
        _scale = scale;

        markTransformDirty();
    }

    void Node::setFlipX(bool flipX)
    {
        _flipX = flipX;

        markTransformDirty();
    }

    void Node::setFlipY(bool flipY)
    {
        _flipY = flipY;

        markTransformDirty();
    }

    void Node::setVisible(bool visible)
    {
        if (visible != _visible)
        {
            _visible = visible;

            setParentVisible(_parentVisible);
        }
    }

    void Node::addToLayer(const LayerWeakPtr& layer)
    {
        _layer = layer;

        if (LayerPtr layer = _layer.lock())
        {
            layer->addNode(std::static_pointer_cast<Node>(shared_from_this()));

            for (NodePtr child : _children)
            {
                child->addToLayer(layer);
            }
        }
    }

    void Node::removeFromLayer()
    {
        if (LayerPtr layer = _layer.lock())
        {
            layer->removeNode(std::static_pointer_cast<Node>(shared_from_this()));

            for (NodePtr child : _children)
            {
                child->removeFromLayer();
            }
        }
    }

    bool Node::pointOn(const Vector2& position) const
    {
        return _boundingBox.containPoint(convertWorldToLocal(position));
    }

    bool Node::rectangleOverlaps(const Rectangle& rectangle) const
    {
        if (_boundingBox.isEmpty())
        {
            return false;
        }

        Vector3 localLeftBottom = Vector3(rectangle.x, rectangle.y, 0.0f);

        const Matrix4& inverseTransform = getInverseTransform();
        inverseTransform.transformPoint(&localLeftBottom);

        Vector3 localRightTop =  Vector3(rectangle.x + rectangle.width, rectangle.y + rectangle.height, 0.0f);

        inverseTransform.transformPoint(&localRightTop);

        if (localLeftBottom.x > _boundingBox.max.x ||
            localLeftBottom.y > _boundingBox.max.y ||
            localRightTop.x < _boundingBox.min.x ||
            localRightTop.y < _boundingBox.min.y)
        {
            return false;
        }

        return true;
    }

    const Matrix4& Node::getTransform() const
    {
        if (_transformDirty)
        {
            calculateTransform();
        }

        return _transform;
    }

    const Matrix4& Node::getInverseTransform() const
    {
        if (_transformDirty)
        {
            calculateTransform();
        }

        if (_inverseTransformDirty)
        {
            calculateInverseTransform();
        }

        return _inverseTransform;
    }

    void Node::updateTransform(const Matrix4& parentTransform)
    {
        _parentTransform = parentTransform;
        calculateTransform();
        _inverseTransformDirty = true;
    }

    Vector2 Node::convertWorldToLocal(const Vector2& position) const
    {
        Vector3 localPosition = position;

        const Matrix4& inverseTransform = getInverseTransform();
        inverseTransform.transformPoint(&localPosition);

        return Vector2(localPosition.x, localPosition.y);
    }

    Vector2 Node::convertLocalToWorld(const Vector2& position) const
    {
        Vector3 worldPosition = position;

        const Matrix4& transform = getTransform();
        transform.transformPoint(&worldPosition);

        return Vector2(worldPosition.x, worldPosition.y);
    }

    bool Node::checkVisibility() const
    {
        if (LayerPtr layer = _layer.lock())
        {
            if (_boundingBox.isEmpty() || _boundingRadius == 0.0f)
            {
                return true;
            }

            Matrix4 mvp = layer->getProjection() * layer->getCamera()->getTransform() * _transform;

            Vector3 position;

            mvp.transformPoint(&position);

            float radius = _boundingRadius * std::max(_scale.x, _scale.y);
            radius /= layer->getCamera()->getZoom();

            Vector2 radiusAxis(radius / (2.0f * Engine::getInstance()->getRenderer()->getSize().width - 1.0f),
                               radius / (2.0f * Engine::getInstance()->getRenderer()->getSize().height - 1.0f));

            if (position.x >= -(1.0f + radiusAxis.x) && position.x <= (1.0f + radiusAxis.x) && position.y >= -(1.0f + radiusAxis.y) && position.y <= (1.0f + radiusAxis.y))
            {
                /*Vector3 corners[4] = {
                    Vector3(_boundingBox.min.x, _boundingBox.min.y, 0.0f),
                    Vector3(_boundingBox.max.x, _boundingBox.min.y, 0.0f),
                    Vector3(_boundingBox.max.x, _boundingBox.max.y, 0.0f),
                    Vector3(_boundingBox.min.x, _boundingBox.max.y, 0.0f)
                };

                uint8_t inCorners = 0;

                for (Vector3& corner : corners)
                {
                    mvp.transformPoint(&corner);

                    if (corner.x >= -1.0f && corner.x <= 1.0f && corner.y >= -1.0f && corner.y <= 1.0f)
                    {
                        return true;
                    }

                    if (corner.x < -1.0f && corner.y < -1.0f) inCorners |= 0x01;
                    if (corner.x > 1.0f && corner.y < -1.0f) inCorners |= 0x02;
                    if (corner.x > 1.0f && corner.y > 1.0f) inCorners |= 0x04;
                    if (corner.x < -1.0f && corner.y > 1.0f) inCorners |= 0x08;
                }

                // bounding box is bigger than screen
                if (inCorners == 0x0F)
                {
                    return true;
                }

                for (uint32_t current = 0; current < 4; ++current)
                {
                    uint32_t next = (current == 3) ? 0 : current + 1;

                    if (linesIntersect(Vector2(corners[current].x, corners[current].y), Vector2(corners[next].x, corners[next].y), Vector2(-1.0f, 1.0f), Vector2(1.0f, 1.0f)) || // top
                        linesIntersect(Vector2(corners[current].x, corners[current].y), Vector2(corners[next].x, corners[next].y), Vector2(-1.0f, -1.0f), Vector2(1.0f, -1.0f)) || // bottom
                        linesIntersect(Vector2(corners[current].x, corners[current].y), Vector2(corners[next].x, corners[next].y), Vector2(1.0f, -1.0f), Vector2(1.0f, 1.0f)) || // right
                        linesIntersect(Vector2(corners[current].x, corners[current].y), Vector2(corners[next].x, corners[next].y), Vector2(-1.0f, -1.0f), Vector2(-1.0f, 1.0f))) // left
                    {
                        return true;
                    }
                }*/

                return true;
            }
        }

        return false;
    }

    void Node::animate(const AnimatorPtr& animator)
    {
        _currentAnimator = animator;

        if (_currentAnimator)
        {
            _currentAnimator->start(std::static_pointer_cast<Node>(shared_from_this()));
        }
    }

    void Node::stopAnimation()
    {
        if (_currentAnimator)
        {
            _currentAnimator->stop();
            _currentAnimator.reset();
        }
    }

    void Node::calculateTransform() const
    {
        Matrix4 translation;
        translation.translate(Vector3(_position.x, _position.y, 0.0f));

        Matrix4 rotation;
        rotation.rotate(Vector3(0.0f, 0.0f, -1.0f), _rotation);

        Vector3 realScale = Vector3(_scale.x * (_flipX ? -1.0f : 1.0f),
                                    _scale.y * (_flipY ? -1.0f : 1.0f),
                                    1.0f);

        Matrix4 scale;
        scale.scale(realScale);

        _transform = _parentTransform * translation * rotation * scale;
        _transformDirty = false;

        for (NodePtr child : _children)
        {
            child->updateTransform(_transform);
        }
    }

    void Node::calculateInverseTransform() const
    {
        if (_transformDirty)
        {
            calculateTransform();
        }

        _inverseTransform = _transform;
        _inverseTransform.invert();
        _inverseTransformDirty = false;
    }

    void Node::markTransformDirty() const
    {
        _transformDirty = true;
        _inverseTransformDirty = true;
    }

    void Node::setParentVisible(bool parentVisible)
    {
        _parentVisible = parentVisible;

        for (const NodePtr& child : _children)
        {
            child->setParentVisible(_visible && _parentVisible);
        }
    }
}
<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015
              Vladimír Vondruš <mosra@centrum.cz>

    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.
*/

#include <Corrade/Containers/Array.h>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/FileToString.h>
#include <Corrade/TestSuite/Compare/Container.h>
#include <Corrade/Utility/Directory.h>

#include "Magnum/Text/AbstractFontConverter.h"
#include "Magnum/Text/GlyphCache.h"

#include "configure.h"

namespace Magnum { namespace Text { namespace Test {

struct AbstractFontConverterTest: TestSuite::Tester {
    explicit AbstractFontConverterTest();

    void convertGlyphs();

    void exportFontToSingleData();
    void exportFontToFile();

    void exportGlyphCacheToSingleData();
    void exportGlyphCacheToFile();

    void importGlyphCacheFromSingleData();
    void importGlyphCacheFromFile();
};

AbstractFontConverterTest::AbstractFontConverterTest() {
    addTests({&AbstractFontConverterTest::convertGlyphs,

              &AbstractFontConverterTest::exportFontToSingleData,
              &AbstractFontConverterTest::exportFontToFile,

              &AbstractFontConverterTest::exportGlyphCacheToSingleData,
              &AbstractFontConverterTest::exportGlyphCacheToFile,

              &AbstractFontConverterTest::importGlyphCacheFromSingleData,
              &AbstractFontConverterTest::importGlyphCacheFromFile});
}

namespace {
    /* *static_cast<GlyphCache*>(nullptr) makes Clang Analyzer grumpy */
    char nullData;
    AbstractFont& nullFont = *reinterpret_cast<AbstractFont*>(nullData);
    GlyphCache& nullGlyphCache = *reinterpret_cast<GlyphCache*>(nullData);
}

void AbstractFontConverterTest::convertGlyphs() {
    class GlyphExporter: public AbstractFontConverter {
        public:
            GlyphExporter(std::u32string& characters): characters(characters) {}

        private:
            Features doFeatures() const override { return Feature::ConvertData|Feature::ExportFont; }

            Containers::Array<char> doExportFontToSingleData(AbstractFont&, GlyphCache&, const std::u32string& characters) const override {
                this->characters = characters;
                return nullptr;
            }

            std::u32string& characters;
    };

    std::u32string characters;
    GlyphExporter exporter(characters);
    exporter.exportFontToSingleData(nullFont, nullGlyphCache, "abC01a0 ");
    CORRADE_COMPARE(characters, U" 01Cab");
}

void AbstractFontConverterTest::exportFontToSingleData() {
    class SingleDataExporter: public Text::AbstractFontConverter {
        private:
            Features doFeatures() const override { return Feature::ConvertData|Feature::ExportFont; }

            Containers::Array<char> doExportFontToSingleData(AbstractFont&, GlyphCache&, const std::u32string&) const override {
                Containers::Array<char> data(1);
                data[0] = '\xee';
                return data;
            }
    };

    /* doExportFontToData() should call doExportFontToSingleData() */
    SingleDataExporter exporter;
    auto ret = exporter.exportFontToData(nullFont, nullGlyphCache, "font.out", {});
    CORRADE_COMPARE(ret.size(), 1);
    CORRADE_COMPARE(ret[0].first, "font.out");
    CORRADE_COMPARE(ret[0].second.size(), 1);
    CORRADE_COMPARE(ret[0].second[0], '\xee');
}

void AbstractFontConverterTest::exportFontToFile() {
    class DataExporter: public Text::AbstractFontConverter {
        private:
            Features doFeatures() const override { return Feature::ConvertData|Feature::ExportFont|Feature::MultiFile; }

            std::vector<std::pair<std::string, Containers::Array<char>>> doExportFontToData(AbstractFont&, GlyphCache&, const std::string& filename, const std::u32string&) const override {
                /* Why the hell GCC 4.9 fails to do proper move so I need to
                   work around that this ugly way?! */
                std::vector<std::pair<std::string, Containers::Array<char>>> ret;
                ret.emplace_back(filename, Containers::Array<char>::from('\xf0'));
                ret.emplace_back(filename + ".data", Containers::Array<char>::from('\xfe', '\xed'));
                return ret;
            }
    };

    /* Remove previous files */
    Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"));
    Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out.data"));

    /* doExportToFile() should call doExportToData() */
    DataExporter exporter;
    bool exported = exporter.exportFontToFile(nullFont, nullGlyphCache, Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"), {});
    CORRADE_VERIFY(exported);
    CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"),
                       "\xf0", TestSuite::Compare::FileToString);
    CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out.data"),
                       "\xfe\xed", TestSuite::Compare::FileToString);
}

void AbstractFontConverterTest::exportGlyphCacheToSingleData() {
    class SingleDataExporter: public Text::AbstractFontConverter {
        private:
            Features doFeatures() const override { return Feature::ConvertData|Feature::ExportGlyphCache; }

            Containers::Array<char> doExportGlyphCacheToSingleData(GlyphCache&) const override {
                return Containers::Array<char>::from('\xee');
            }
    };

    /* doExportGlyphCacheToData() should call doExportGlyphCacheToSingleData() */
    SingleDataExporter exporter;
    auto ret = exporter.exportGlyphCacheToData(nullGlyphCache, "font.out");
    CORRADE_COMPARE(ret.size(), 1);
    CORRADE_COMPARE(ret[0].first, "font.out");
    CORRADE_COMPARE_AS(ret[0].second, Containers::Array<char>::from('\xee'), TestSuite::Compare::Container);
}

void AbstractFontConverterTest::exportGlyphCacheToFile() {
    class DataExporter: public Text::AbstractFontConverter {
        private:
            Features doFeatures() const override { return Feature::ConvertData|Feature::ExportGlyphCache|Feature::MultiFile; }

            std::vector<std::pair<std::string, Containers::Array<char>>> doExportGlyphCacheToData(GlyphCache&, const std::string& filename) const override {
                /* Why the hell GCC 4.9 fails to do proper move so I need to
                   work around that this ugly way?! */
                std::vector<std::pair<std::string, Containers::Array<char>>> ret;
                ret.emplace_back(filename, Containers::Array<char>::from('\xf0'));
                ret.emplace_back(filename + ".data", Containers::Array<char>::from('\xfe', '\xed'));
                return ret;
            }
    };

    /* Remove previous files */
    Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out"));
    Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out.data"));

    /* doExportGlyphCacheToFile() should call doExportGlyphCacheToData() */
    DataExporter exporter;
    bool exported = exporter.exportGlyphCacheToFile(nullGlyphCache, Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out"));
    CORRADE_VERIFY(exported);
    CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out"),
                       "\xf0", TestSuite::Compare::FileToString);
    CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out.data"),
                       "\xfe\xed", TestSuite::Compare::FileToString);
}

namespace {

class SingleGlyphCacheDataImporter: public Text::AbstractFontConverter {
    private:
        Features doFeatures() const override { return Feature::ConvertData|Feature::ImportGlyphCache; }

        std::unique_ptr<GlyphCache> doImportGlyphCacheFromSingleData(const Containers::ArrayView<const char> data) const override {
            if(data.size() == 1 && data[0] == '\xa5')
                return std::unique_ptr<GlyphCache>(reinterpret_cast<GlyphCache*>(0xdeadbeef));
            return nullptr;
        }
};

}

void AbstractFontConverterTest::importGlyphCacheFromSingleData() {
    /* doImportFromData() should call doImportFromSingleData() */
    SingleGlyphCacheDataImporter importer;
    const char data[] = {'\xa5'};
    std::unique_ptr<GlyphCache> cache = importer.importGlyphCacheFromData({{{}, data}});
    CORRADE_COMPARE(cache.get(), reinterpret_cast<GlyphCache*>(0xdeadbeef));

    /* The pointer is invalid, avoid deletion */
    cache.release();
}

void AbstractFontConverterTest::importGlyphCacheFromFile() {
    /* doImportFromFile() should call doImportFromSingleData() */
    SingleGlyphCacheDataImporter importer;
    std::unique_ptr<GlyphCache> cache = importer.importGlyphCacheFromFile(Utility::Directory::join(TEXT_TEST_DIR, "data.bin"));
    CORRADE_COMPARE(cache.get(), reinterpret_cast<GlyphCache*>(0xdeadbeef));

    /* The pointer is invalid, avoid deletion */
    cache.release();
}

}}}

CORRADE_TEST_MAIN(Magnum::Text::Test::AbstractFontConverterTest)
<commit_msg>Text: prefix private member variables with underscore.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015
              Vladimír Vondruš <mosra@centrum.cz>

    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.
*/

#include <Corrade/Containers/Array.h>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/FileToString.h>
#include <Corrade/TestSuite/Compare/Container.h>
#include <Corrade/Utility/Directory.h>

#include "Magnum/Text/AbstractFontConverter.h"
#include "Magnum/Text/GlyphCache.h"

#include "configure.h"

namespace Magnum { namespace Text { namespace Test {

struct AbstractFontConverterTest: TestSuite::Tester {
    explicit AbstractFontConverterTest();

    void convertGlyphs();

    void exportFontToSingleData();
    void exportFontToFile();

    void exportGlyphCacheToSingleData();
    void exportGlyphCacheToFile();

    void importGlyphCacheFromSingleData();
    void importGlyphCacheFromFile();
};

AbstractFontConverterTest::AbstractFontConverterTest() {
    addTests({&AbstractFontConverterTest::convertGlyphs,

              &AbstractFontConverterTest::exportFontToSingleData,
              &AbstractFontConverterTest::exportFontToFile,

              &AbstractFontConverterTest::exportGlyphCacheToSingleData,
              &AbstractFontConverterTest::exportGlyphCacheToFile,

              &AbstractFontConverterTest::importGlyphCacheFromSingleData,
              &AbstractFontConverterTest::importGlyphCacheFromFile});
}

namespace {
    /* *static_cast<GlyphCache*>(nullptr) makes Clang Analyzer grumpy */
    char nullData;
    AbstractFont& nullFont = *reinterpret_cast<AbstractFont*>(nullData);
    GlyphCache& nullGlyphCache = *reinterpret_cast<GlyphCache*>(nullData);
}

void AbstractFontConverterTest::convertGlyphs() {
    class GlyphExporter: public AbstractFontConverter {
        public:
            GlyphExporter(std::u32string& characters): _characters{characters} {}

        private:
            Features doFeatures() const override { return Feature::ConvertData|Feature::ExportFont; }

            Containers::Array<char> doExportFontToSingleData(AbstractFont&, GlyphCache&, const std::u32string& characters) const override {
                _characters = characters;
                return nullptr;
            }

            std::u32string& _characters;
    };

    std::u32string characters;
    GlyphExporter exporter(characters);
    exporter.exportFontToSingleData(nullFont, nullGlyphCache, "abC01a0 ");
    CORRADE_COMPARE(characters, U" 01Cab");
}

void AbstractFontConverterTest::exportFontToSingleData() {
    class SingleDataExporter: public Text::AbstractFontConverter {
        private:
            Features doFeatures() const override { return Feature::ConvertData|Feature::ExportFont; }

            Containers::Array<char> doExportFontToSingleData(AbstractFont&, GlyphCache&, const std::u32string&) const override {
                Containers::Array<char> data(1);
                data[0] = '\xee';
                return data;
            }
    };

    /* doExportFontToData() should call doExportFontToSingleData() */
    SingleDataExporter exporter;
    auto ret = exporter.exportFontToData(nullFont, nullGlyphCache, "font.out", {});
    CORRADE_COMPARE(ret.size(), 1);
    CORRADE_COMPARE(ret[0].first, "font.out");
    CORRADE_COMPARE(ret[0].second.size(), 1);
    CORRADE_COMPARE(ret[0].second[0], '\xee');
}

void AbstractFontConverterTest::exportFontToFile() {
    class DataExporter: public Text::AbstractFontConverter {
        private:
            Features doFeatures() const override { return Feature::ConvertData|Feature::ExportFont|Feature::MultiFile; }

            std::vector<std::pair<std::string, Containers::Array<char>>> doExportFontToData(AbstractFont&, GlyphCache&, const std::string& filename, const std::u32string&) const override {
                /* Why the hell GCC 4.9 fails to do proper move so I need to
                   work around that this ugly way?! */
                std::vector<std::pair<std::string, Containers::Array<char>>> ret;
                ret.emplace_back(filename, Containers::Array<char>::from('\xf0'));
                ret.emplace_back(filename + ".data", Containers::Array<char>::from('\xfe', '\xed'));
                return ret;
            }
    };

    /* Remove previous files */
    Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"));
    Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out.data"));

    /* doExportToFile() should call doExportToData() */
    DataExporter exporter;
    bool exported = exporter.exportFontToFile(nullFont, nullGlyphCache, Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"), {});
    CORRADE_VERIFY(exported);
    CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"),
                       "\xf0", TestSuite::Compare::FileToString);
    CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out.data"),
                       "\xfe\xed", TestSuite::Compare::FileToString);
}

void AbstractFontConverterTest::exportGlyphCacheToSingleData() {
    class SingleDataExporter: public Text::AbstractFontConverter {
        private:
            Features doFeatures() const override { return Feature::ConvertData|Feature::ExportGlyphCache; }

            Containers::Array<char> doExportGlyphCacheToSingleData(GlyphCache&) const override {
                return Containers::Array<char>::from('\xee');
            }
    };

    /* doExportGlyphCacheToData() should call doExportGlyphCacheToSingleData() */
    SingleDataExporter exporter;
    auto ret = exporter.exportGlyphCacheToData(nullGlyphCache, "font.out");
    CORRADE_COMPARE(ret.size(), 1);
    CORRADE_COMPARE(ret[0].first, "font.out");
    CORRADE_COMPARE_AS(ret[0].second, Containers::Array<char>::from('\xee'), TestSuite::Compare::Container);
}

void AbstractFontConverterTest::exportGlyphCacheToFile() {
    class DataExporter: public Text::AbstractFontConverter {
        private:
            Features doFeatures() const override { return Feature::ConvertData|Feature::ExportGlyphCache|Feature::MultiFile; }

            std::vector<std::pair<std::string, Containers::Array<char>>> doExportGlyphCacheToData(GlyphCache&, const std::string& filename) const override {
                /* Why the hell GCC 4.9 fails to do proper move so I need to
                   work around that this ugly way?! */
                std::vector<std::pair<std::string, Containers::Array<char>>> ret;
                ret.emplace_back(filename, Containers::Array<char>::from('\xf0'));
                ret.emplace_back(filename + ".data", Containers::Array<char>::from('\xfe', '\xed'));
                return ret;
            }
    };

    /* Remove previous files */
    Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out"));
    Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out.data"));

    /* doExportGlyphCacheToFile() should call doExportGlyphCacheToData() */
    DataExporter exporter;
    bool exported = exporter.exportGlyphCacheToFile(nullGlyphCache, Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out"));
    CORRADE_VERIFY(exported);
    CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out"),
                       "\xf0", TestSuite::Compare::FileToString);
    CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out.data"),
                       "\xfe\xed", TestSuite::Compare::FileToString);
}

namespace {

class SingleGlyphCacheDataImporter: public Text::AbstractFontConverter {
    private:
        Features doFeatures() const override { return Feature::ConvertData|Feature::ImportGlyphCache; }

        std::unique_ptr<GlyphCache> doImportGlyphCacheFromSingleData(const Containers::ArrayView<const char> data) const override {
            if(data.size() == 1 && data[0] == '\xa5')
                return std::unique_ptr<GlyphCache>(reinterpret_cast<GlyphCache*>(0xdeadbeef));
            return nullptr;
        }
};

}

void AbstractFontConverterTest::importGlyphCacheFromSingleData() {
    /* doImportFromData() should call doImportFromSingleData() */
    SingleGlyphCacheDataImporter importer;
    const char data[] = {'\xa5'};
    std::unique_ptr<GlyphCache> cache = importer.importGlyphCacheFromData({{{}, data}});
    CORRADE_COMPARE(cache.get(), reinterpret_cast<GlyphCache*>(0xdeadbeef));

    /* The pointer is invalid, avoid deletion */
    cache.release();
}

void AbstractFontConverterTest::importGlyphCacheFromFile() {
    /* doImportFromFile() should call doImportFromSingleData() */
    SingleGlyphCacheDataImporter importer;
    std::unique_ptr<GlyphCache> cache = importer.importGlyphCacheFromFile(Utility::Directory::join(TEXT_TEST_DIR, "data.bin"));
    CORRADE_COMPARE(cache.get(), reinterpret_cast<GlyphCache*>(0xdeadbeef));

    /* The pointer is invalid, avoid deletion */
    cache.release();
}

}}}

CORRADE_TEST_MAIN(Magnum::Text::Test::AbstractFontConverterTest)
<|endoftext|>