<commit_before>#include <QString>
#include <QtTest>
#include <mainWindow.h>

class TestTest : public QObject
{
    Q_OBJECT

public:
    TestTest();

private Q_SLOTS:
    void testCase1();
    void testInit();
};

TestTest::TestTest()
{
}

void TestTest::testCase1()
{
    QVERIFY2(true, "Failure");
}

//void TestTest::testInit()
//{
//    MainWindow window;
//    window.initWindow("Title window");

//    QCOMPARE(600, window.size().height());
//    QCOMPARE(800,  window.size().width());
//    QCOMPARE(QString("Title window"), window.windowTitle());

//}

QTEST_APPLESS_MAIN(TestTest)

#include "AurebeshProjectTest.moc"
<commit_msg>no message<commit_after>#include <QString>
#include <QtTest>
#include <mainWindow.h>

class TestTest : public QObject
{
    Q_OBJECT

public:
    TestTest();

private Q_SLOTS:
    void testCase1();
    void testInit();
};

TestTest::TestTest()
{
}

void TestTest::testCase1()
{
    QVERIFY2(true, "Failure");
}

void TestTest::testInit()
{
     QVERIFY2(true, "Failure");
//    MainWindow window;
//    window.initWindow("Title window");

//    QCOMPARE(600, window.size().height());
//    QCOMPARE(800,  window.size().width());
//    QCOMPARE(QString("Title window"), window.windowTitle());

}

QTEST_APPLESS_MAIN(TestTest)

#include "AurebeshProjectTest.moc"
<|endoftext|>


<commit_before>/*!
 * \page TravelChoiceTestSuite_cpp Command-Line Test to Demonstrate How To Test the Travel CCM Project
 * \code
 */
// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <sstream>
#include <fstream>
#include <string>
// Boost Unit Test Framework (UTF)
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE TravelCCMTest
#include <boost/test/unit_test.hpp>
// StdAir
#include <stdair/basic/BasLogParams.hpp>
#include <stdair/basic/BasDBParams.hpp>
#include <stdair/basic/BasFileMgr.hpp>
#include <stdair/basic/PassengerChoiceModel.hpp>
#include <stdair/bom/TravelSolutionStruct.hpp>
#include <stdair/bom/BookingRequestStruct.hpp>
#include <stdair/service/Logger.hpp>
// TravelCCM
#include <travelccm/TRAVELCCM_Service.hpp>
#include <travelccm/config/travelccm-paths.hpp>

namespace boost_utf = boost::unit_test;

// (Boost) Unit Test XML Report
std::ofstream utfReportStream ("TravelChoiceTestSuite_utfresults.xml");

/**
 * Configuration for the Boost Unit Test Framework (UTF)
 */
struct UnitTestConfig {
  /** Constructor. */
  UnitTestConfig() {
    boost_utf::unit_test_log.set_stream (utfReportStream);
#if defined(BOOST_VERSION) && BOOST_VERSION >= 105900
    boost_utf::unit_test_log.set_format (boost_utf::OF_XML);
#else // BOOST_VERSION
    boost_utf::unit_test_log.set_format (boost_utf::XML);
#endif // BOOST_VERSION
    boost_utf::unit_test_log.set_threshold_level (boost_utf::log_test_units);
    //boost_utf::unit_test_log.set_threshold_level (boost_utf::log_successful_tests);
  }
  /** Destructor. */
  ~UnitTestConfig() {
  }
};

// //////////////////////////////////////////////////////////////////////
/**
 * Choose a fare option among the list of travel solutions
 */
void testTravelCCMHelper (const unsigned short iTestFlag,
                          const stdair::PassengerChoiceModel::EN_PassengerChoiceModel& iPassengerChoiceModel,
                          const unsigned int iExpectedPrice) {

  // Output log File
  std::ostringstream oStr;
  oStr << "TravelChoiceTestSuite_" << iTestFlag << ".log";
  const stdair::Filename_T lLogFilename (oStr.str());

  // Set the log parameters
  std::ofstream logOutputFile;
  // Open and clean the log outputfile
  logOutputFile.open (lLogFilename.c_str());
  logOutputFile.clear();

  // Initialise the service context
  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);

  // Build the BOM tree
  TRAVELCCM::TRAVELCCM_Service travelccmService (lLogParams);
  travelccmService.buildSampleBom ();

  // DEBUG
  STDAIR_LOG_DEBUG ("Welcome to TravelCCM");

  // Build a list of travel solutions
  const stdair::BookingRequestStruct& lBookingRequest =
    travelccmService.buildSampleBookingRequest();

  // DEBUG
  STDAIR_LOG_DEBUG ("Booking request: " << lBookingRequest.display());

  // Build the sample BOM tree
  stdair::TravelSolutionList_T lTSList;
  travelccmService.buildSampleTravelSolutions (lTSList);

  // DEBUG: Display the list of travel solutions
  const std::string& lCSVDump = travelccmService.csvDisplay (lTSList);
  STDAIR_LOG_DEBUG (lCSVDump);

  // Choose a travel solution
  const stdair::TravelSolutionStruct* lTS_ptr =
    travelccmService.chooseTravelSolution (lTSList, lBookingRequest, iPassengerChoiceModel);

  // Check that a solution has been found
  BOOST_REQUIRE_MESSAGE (lTS_ptr != NULL,
                         "No travel solution can be found for "
                         << lBookingRequest.display()
                         << " within the following list of travel solutions. "
                         << lCSVDump);

  STDAIR_LOG_DEBUG (lTS_ptr->describe());

  // Retrieve the chosen fare option
  stdair::FareOptionStruct lFareOption = lTS_ptr->getChosenFareOption();

  // DEBUG
  std::ostringstream oMessageExpectedPrice;
  oMessageExpectedPrice << "The price chosen by the passenger is: "
                        << lFareOption.getFare() << " Euros. It is expected to be "
                        << iExpectedPrice << " Euros.";
  STDAIR_LOG_DEBUG (oMessageExpectedPrice.str());

  // Check that the price corresponds to the expected one
  BOOST_CHECK_EQUAL (std::floor (lFareOption.getFare() + 0.5), iExpectedPrice);

  BOOST_CHECK_MESSAGE (std::floor (lFareOption.getFare() + 0.5)
                       == iExpectedPrice, oMessageExpectedPrice.str());

  // Close the log file
  logOutputFile.close();

}

/**
 * Choose a fare option among the list of travel solutions
 */
void testAllTravelCCMHelper (const unsigned short iTestFlag) {

  // Output log File
  std::ostringstream oStr;
  oStr << "TravelChoiceTestSuite_" << iTestFlag << ".log";
  const stdair::Filename_T lLogFilename (oStr.str());

  // Set the log parameters
  std::ofstream logOutputFile;
  // Open and clean the log outputfile
  logOutputFile.open (lLogFilename.c_str());
  logOutputFile.clear();

  // Initialise the service context
  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);

  // Build the BOM tree
  TRAVELCCM::TRAVELCCM_Service travelccmService (lLogParams);
  travelccmService.buildSampleBom ();

  // DEBUG
  STDAIR_LOG_DEBUG ("Welcome to TravelCCM");

  // Build a list of travel solutions
  const stdair::BookingRequestStruct& lBookingRequest =
    travelccmService.buildSampleBookingRequest();

  // DEBUG
  STDAIR_LOG_DEBUG ("Booking request: " << lBookingRequest.display());

  // Build the sample BOM tree
  stdair::TravelSolutionList_T lTSList;
  travelccmService.buildSampleTravelSolutions (lTSList);

  // DEBUG: Display the list of travel solutions
  const std::string& lCSVDump = travelccmService.csvDisplay (lTSList);
  STDAIR_LOG_DEBUG (lCSVDump);

  // Choose a travel solution with the hard restriction method.
  const stdair::TravelSolutionStruct* lTS_HardRestriction_ptr =
    travelccmService.chooseTravelSolution
    (lTSList, lBookingRequest,
     stdair::PassengerChoiceModel::HARD_RESTRICTION);

  STDAIR_LOG_DEBUG ("Chosen travel solution with the Hard Restriction model: "
		    + lTS_HardRestriction_ptr->describe());

  // Choose a travel solution with the price oriented model
  const stdair::TravelSolutionStruct* lTS_Price_Oriented_ptr =
    travelccmService.chooseTravelSolution
    (lTSList, lBookingRequest,
     stdair::PassengerChoiceModel::PRICE_ORIENTED);

  STDAIR_LOG_DEBUG ("Chosen travel solution with the Price Oriented model: "
		    + lTS_Price_Oriented_ptr->describe());

  // Choose a travel solution with the hybrid model
  const stdair::TravelSolutionStruct* lTS_Hybrid_ptr =
    travelccmService.chooseTravelSolution
    (lTSList, lBookingRequest,
     stdair::PassengerChoiceModel::HYBRID);

  STDAIR_LOG_DEBUG ("Chosen travel solution with the Hybrid model: " +
		    lTS_Hybrid_ptr->describe());

  // Close the log file
  logOutputFile.close();

}

// /////////////// Main: Unit Test Suite //////////////

// Set the UTF configuration (re-direct the output to a specific file)
BOOST_GLOBAL_FIXTURE (UnitTestConfig);

// Start the test suite
BOOST_AUTO_TEST_SUITE (master_test_suite)

/**
 * Test the hard restriction model
 */
BOOST_AUTO_TEST_CASE (simple_hard_restriction_model_test) {

  /**
   * As of September 2012, the fare option chosen by the hard restriction model
   * is valued to 1000 Euros.
   */
  const unsigned int lExpectedPrice = 1000;

  BOOST_CHECK_NO_THROW (testTravelCCMHelper
                        (0,
                         stdair::PassengerChoiceModel::HARD_RESTRICTION,
                         lExpectedPrice));
}

/**
 * Test the price oriented model
 */
BOOST_AUTO_TEST_CASE (simple_price_oriented_model_test) {

  /**
   * As of September 2012, the fare option chosen by the price oriented model
   * is valued to 900 Euros.
   */
  const unsigned int lExpectedPrice = 900;

  BOOST_CHECK_NO_THROW (testTravelCCMHelper
                        (1,
                         stdair::PassengerChoiceModel::PRICE_ORIENTED,
                         lExpectedPrice));
}

/**
 * Test the hybrid model
 */
BOOST_AUTO_TEST_CASE (simple_hybrid_model_test) {

  /**
   * As of September 2012, the fare option chosen by the price oriented model
   * is valued to 920 Euros.
   */
  const unsigned int lExpectedPrice = 920;

  BOOST_CHECK_NO_THROW (testTravelCCMHelper
                        (2,
                         stdair::PassengerChoiceModel::HYBRID,
                         lExpectedPrice));
}

/**
 * Test all models.
 */
BOOST_AUTO_TEST_CASE (all_models_test) {

  BOOST_CHECK_NO_THROW (testAllTravelCCMHelper(3));
}

// End the test suite
BOOST_AUTO_TEST_SUITE_END()

/*!
 * \endcode
 */
<commit_msg>BOOST_VERSION => BOOST_VERSION_MACRO<commit_after>/*!
 * \page TravelChoiceTestSuite_cpp Command-Line Test to Demonstrate How To Test the Travel CCM Project
 * \code
 */
// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <sstream>
#include <fstream>
#include <string>
// Boost Unit Test Framework (UTF)
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE TravelCCMTest
#include <boost/test/unit_test.hpp>
// StdAir
#include <stdair/basic/BasLogParams.hpp>
#include <stdair/basic/BasDBParams.hpp>
#include <stdair/basic/BasFileMgr.hpp>
#include <stdair/basic/PassengerChoiceModel.hpp>
#include <stdair/bom/TravelSolutionStruct.hpp>
#include <stdair/bom/BookingRequestStruct.hpp>
#include <stdair/service/Logger.hpp>
// TravelCCM
#include <travelccm/TRAVELCCM_Service.hpp>
#include <travelccm/config/travelccm-paths.hpp>

namespace boost_utf = boost::unit_test;

// (Boost) Unit Test XML Report
std::ofstream utfReportStream ("TravelChoiceTestSuite_utfresults.xml");

/**
 * Configuration for the Boost Unit Test Framework (UTF)
 */
struct UnitTestConfig {
  /** Constructor. */
  UnitTestConfig() {
    boost_utf::unit_test_log.set_stream (utfReportStream);
#if BOOST_VERSION_MACRO >= 105900
    boost_utf::unit_test_log.set_format (boost_utf::OF_XML);
#else // BOOST_VERSION_MACRO
    boost_utf::unit_test_log.set_format (boost_utf::XML);
#endif // BOOST_VERSION_MACRO
    boost_utf::unit_test_log.set_threshold_level (boost_utf::log_test_units);
    //boost_utf::unit_test_log.set_threshold_level (boost_utf::log_successful_tests);
  }
  /** Destructor. */
  ~UnitTestConfig() {
  }
};

// //////////////////////////////////////////////////////////////////////
/**
 * Choose a fare option among the list of travel solutions
 */
void testTravelCCMHelper (const unsigned short iTestFlag,
                          const stdair::PassengerChoiceModel::EN_PassengerChoiceModel& iPassengerChoiceModel,
                          const unsigned int iExpectedPrice) {

  // Output log File
  std::ostringstream oStr;
  oStr << "TravelChoiceTestSuite_" << iTestFlag << ".log";
  const stdair::Filename_T lLogFilename (oStr.str());

  // Set the log parameters
  std::ofstream logOutputFile;
  // Open and clean the log outputfile
  logOutputFile.open (lLogFilename.c_str());
  logOutputFile.clear();

  // Initialise the service context
  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);

  // Build the BOM tree
  TRAVELCCM::TRAVELCCM_Service travelccmService (lLogParams);
  travelccmService.buildSampleBom ();

  // DEBUG
  STDAIR_LOG_DEBUG ("Welcome to TravelCCM");

  // Build a list of travel solutions
  const stdair::BookingRequestStruct& lBookingRequest =
    travelccmService.buildSampleBookingRequest();

  // DEBUG
  STDAIR_LOG_DEBUG ("Booking request: " << lBookingRequest.display());

  // Build the sample BOM tree
  stdair::TravelSolutionList_T lTSList;
  travelccmService.buildSampleTravelSolutions (lTSList);

  // DEBUG: Display the list of travel solutions
  const std::string& lCSVDump = travelccmService.csvDisplay (lTSList);
  STDAIR_LOG_DEBUG (lCSVDump);

  // Choose a travel solution
  const stdair::TravelSolutionStruct* lTS_ptr =
    travelccmService.chooseTravelSolution (lTSList, lBookingRequest, iPassengerChoiceModel);

  // Check that a solution has been found
  BOOST_REQUIRE_MESSAGE (lTS_ptr != NULL,
                         "No travel solution can be found for "
                         << lBookingRequest.display()
                         << " within the following list of travel solutions. "
                         << lCSVDump);

  STDAIR_LOG_DEBUG (lTS_ptr->describe());

  // Retrieve the chosen fare option
  stdair::FareOptionStruct lFareOption = lTS_ptr->getChosenFareOption();

  // DEBUG
  std::ostringstream oMessageExpectedPrice;
  oMessageExpectedPrice << "The price chosen by the passenger is: "
                        << lFareOption.getFare() << " Euros. It is expected to be "
                        << iExpectedPrice << " Euros.";
  STDAIR_LOG_DEBUG (oMessageExpectedPrice.str());

  // Check that the price corresponds to the expected one
  BOOST_CHECK_EQUAL (std::floor (lFareOption.getFare() + 0.5), iExpectedPrice);

  BOOST_CHECK_MESSAGE (std::floor (lFareOption.getFare() + 0.5)
                       == iExpectedPrice, oMessageExpectedPrice.str());

  // Close the log file
  logOutputFile.close();

}

/**
 * Choose a fare option among the list of travel solutions
 */
void testAllTravelCCMHelper (const unsigned short iTestFlag) {

  // Output log File
  std::ostringstream oStr;
  oStr << "TravelChoiceTestSuite_" << iTestFlag << ".log";
  const stdair::Filename_T lLogFilename (oStr.str());

  // Set the log parameters
  std::ofstream logOutputFile;
  // Open and clean the log outputfile
  logOutputFile.open (lLogFilename.c_str());
  logOutputFile.clear();

  // Initialise the service context
  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);

  // Build the BOM tree
  TRAVELCCM::TRAVELCCM_Service travelccmService (lLogParams);
  travelccmService.buildSampleBom ();

  // DEBUG
  STDAIR_LOG_DEBUG ("Welcome to TravelCCM");

  // Build a list of travel solutions
  const stdair::BookingRequestStruct& lBookingRequest =
    travelccmService.buildSampleBookingRequest();

  // DEBUG
  STDAIR_LOG_DEBUG ("Booking request: " << lBookingRequest.display());

  // Build the sample BOM tree
  stdair::TravelSolutionList_T lTSList;
  travelccmService.buildSampleTravelSolutions (lTSList);

  // DEBUG: Display the list of travel solutions
  const std::string& lCSVDump = travelccmService.csvDisplay (lTSList);
  STDAIR_LOG_DEBUG (lCSVDump);

  // Choose a travel solution with the hard restriction method.
  const stdair::TravelSolutionStruct* lTS_HardRestriction_ptr =
    travelccmService.chooseTravelSolution
    (lTSList, lBookingRequest,
     stdair::PassengerChoiceModel::HARD_RESTRICTION);

  STDAIR_LOG_DEBUG ("Chosen travel solution with the Hard Restriction model: "
		    + lTS_HardRestriction_ptr->describe());

  // Choose a travel solution with the price oriented model
  const stdair::TravelSolutionStruct* lTS_Price_Oriented_ptr =
    travelccmService.chooseTravelSolution
    (lTSList, lBookingRequest,
     stdair::PassengerChoiceModel::PRICE_ORIENTED);

  STDAIR_LOG_DEBUG ("Chosen travel solution with the Price Oriented model: "
		    + lTS_Price_Oriented_ptr->describe());

  // Choose a travel solution with the hybrid model
  const stdair::TravelSolutionStruct* lTS_Hybrid_ptr =
    travelccmService.chooseTravelSolution
    (lTSList, lBookingRequest,
     stdair::PassengerChoiceModel::HYBRID);

  STDAIR_LOG_DEBUG ("Chosen travel solution with the Hybrid model: " +
		    lTS_Hybrid_ptr->describe());

  // Close the log file
  logOutputFile.close();

}

// /////////////// Main: Unit Test Suite //////////////

// Set the UTF configuration (re-direct the output to a specific file)
BOOST_GLOBAL_FIXTURE (UnitTestConfig);

// Start the test suite
BOOST_AUTO_TEST_SUITE (master_test_suite)

/**
 * Test the hard restriction model
 */
BOOST_AUTO_TEST_CASE (simple_hard_restriction_model_test) {

  /**
   * As of September 2012, the fare option chosen by the hard restriction model
   * is valued to 1000 Euros.
   */
  const unsigned int lExpectedPrice = 1000;

  BOOST_CHECK_NO_THROW (testTravelCCMHelper
                        (0,
                         stdair::PassengerChoiceModel::HARD_RESTRICTION,
                         lExpectedPrice));
}

/**
 * Test the price oriented model
 */
BOOST_AUTO_TEST_CASE (simple_price_oriented_model_test) {

  /**
   * As of September 2012, the fare option chosen by the price oriented model
   * is valued to 900 Euros.
   */
  const unsigned int lExpectedPrice = 900;

  BOOST_CHECK_NO_THROW (testTravelCCMHelper
                        (1,
                         stdair::PassengerChoiceModel::PRICE_ORIENTED,
                         lExpectedPrice));
}

/**
 * Test the hybrid model
 */
BOOST_AUTO_TEST_CASE (simple_hybrid_model_test) {

  /**
   * As of September 2012, the fare option chosen by the price oriented model
   * is valued to 920 Euros.
   */
  const unsigned int lExpectedPrice = 920;

  BOOST_CHECK_NO_THROW (testTravelCCMHelper
                        (2,
                         stdair::PassengerChoiceModel::HYBRID,
                         lExpectedPrice));
}

/**
 * Test all models.
 */
BOOST_AUTO_TEST_CASE (all_models_test) {

  BOOST_CHECK_NO_THROW (testAllTravelCCMHelper(3));
}

// End the test suite
BOOST_AUTO_TEST_SUITE_END()

/*!
 * \endcode
 */
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "otbWrapperTypes.h"

namespace otb
{
namespace Wrapper
{

std::string ParameterTypeToString(ParameterType type)
{
  return parameterTypesStrings[type];
}

ParameterType ParameterStringToType(const std::string& str)
{
  for (auto i = 0; i < parameterTypesStrings.size(); i++)
  {
    if (str == parameterTypesStrings[i])
    {
      return ParameterType(i);
    }
  }
  itkGenericExceptionMacro("Cannot convert string '" << str << "' to parameter type.");
}
} // namespace Wrapper
} // namespace otb
<commit_msg>WRG: fix warning about type conversion<commit_after>/*
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "otbWrapperTypes.h"

namespace otb
{
namespace Wrapper
{

std::string ParameterTypeToString(ParameterType type)
{
  return parameterTypesStrings[type];
}

ParameterType ParameterStringToType(const std::string& str)
{
  for (std::size_t i = 0; i < parameterTypesStrings.size(); i++)
  {
    if (str == parameterTypesStrings[i])
    {
      return ParameterType(i);
    }
  }
  itkGenericExceptionMacro("Cannot convert string '" << str << "' to parameter type.");
}
} // namespace Wrapper
} // namespace otb
<|endoftext|>


<commit_before>/**
 * StimulusDisplay.cpp
 *
 * History:
 * Dave Cox on ??/??/?? - Created.
 * Paul Jankunas on 05/23/05 - Fixed spacing.
 *
 * Copyright 2005 MIT.  All rights reserved.
 */

#include "OpenGLContextManager.h"
#include "Stimulus.h"
#include "StimulusNode.h"
#include "Utilities.h"
#include "StandardVariables.h"
#include "Experiment.h"
#include "StandardVariables.h"
#include "ComponentRegistry.h"
#include "VariableNotification.h"

#include "boost/bind.hpp"

#ifdef	__APPLE__
	#include <AGL/agl.h>
	#include <OpenGL/gl.h>
	#include <OpenGL/glu.h>
    #include <CoreVideo/CVHostTime.h>
#elif	linux
	// TODO: where are these in linux?
#endif

#if M_OPENGL_SHARED_STATE == 1
    #define RENDER_ONCE
#endif

using namespace mw;

/**********************************************************************
 *                  StimulusDisplay Methods
 **********************************************************************/
StimulusDisplay::StimulusDisplay() {
    current_context_index = -1;

    // defer creation of the display chain until after the stimulus display has been created
    display_stack = shared_ptr< LinkedList<StimulusNode> >(new LinkedList<StimulusNode>());

	setDisplayBounds();

    opengl_context_manager = OpenGLContextManager::instance();
    clock = Clock::instance();

    if (kCVReturnSuccess != CVDisplayLinkCreateWithActiveCGDisplays(&displayLink)) {
        throw SimpleException("Unable to create display link");
    }

    stateSystemNotification = shared_ptr<VariableCallbackNotification>(new VariableCallbackNotification(boost::bind(&StimulusDisplay::stateSystemCallback, this, _1, _2)));
    state_system_mode->addNotification(stateSystemNotification);
}

StimulusDisplay::~StimulusDisplay(){
    stateSystemNotification->remove();
    CVDisplayLinkRelease(displayLink);
}

void StimulusDisplay::setCurrent(int i){
    if ((i >= getNContexts()) || (i < 0)) {
        merror(M_DISPLAY_MESSAGE_DOMAIN, "invalid context index (%d)", i);
        return;
    }

	current_context_index = i;
	opengl_context_manager->setCurrent(context_ids[i]);
}

shared_ptr<StimulusNode> StimulusDisplay::addStimulus(shared_ptr<Stimulus> stim) {
    if(!stim) {
        mprintf("Attempt to load NULL stimulus");
        return shared_ptr<StimulusNode>();
    }

	shared_ptr<StimulusNode> stimnode(new StimulusNode(stim));

    display_stack->addToFront(stimnode);

	return stimnode;
}

void StimulusDisplay::addStimulusNode(shared_ptr<StimulusNode> stimnode) {
    if(!stimnode) {
        mprintf("Attempt to load NULL stimulus");
        return;
    }

	// remove it, in case it already belongs to a list
	stimnode->remove();

	display_stack->addToFront(stimnode);  // TODO
}

void StimulusDisplay::setDisplayBounds(){
  shared_ptr<mw::ComponentRegistry> reg = mw::ComponentRegistry::getSharedRegistry();
  shared_ptr<Variable> main_screen_info = reg->getVariable(MAIN_SCREEN_INFO_TAGNAME);

 Datum display_info = *main_screen_info; // from standard variables
	if(display_info.getDataType() == M_DICTIONARY &&
	   display_info.hasKey(M_DISPLAY_WIDTH_KEY) &&
	   display_info.hasKey(M_DISPLAY_HEIGHT_KEY) &&
	   display_info.hasKey(M_DISPLAY_DISTANCE_KEY)){

		GLdouble width_unknown_units = display_info.getElement(M_DISPLAY_WIDTH_KEY);
		GLdouble height_unknown_units = display_info.getElement(M_DISPLAY_HEIGHT_KEY);
		GLdouble distance_unknown_units = display_info.getElement(M_DISPLAY_DISTANCE_KEY);

		GLdouble half_width_deg = (180. / M_PI) * atan((width_unknown_units/2.)/distance_unknown_units);
		GLdouble half_height_deg = half_width_deg * height_unknown_units / width_unknown_units;
		//GLdouble half_height_deg = (180. / M_PI) * atan((height_unknown_units/2.)/distance_unknown_units);

		left = -half_width_deg;
		right = half_width_deg;
		top = half_height_deg;
		bottom = -half_height_deg;
	} else {
		left = M_STIMULUS_DISPLAY_LEFT_EDGE;
		right = M_STIMULUS_DISPLAY_RIGHT_EDGE;
		top = M_STIMULUS_DISPLAY_TOP_EDGE;
		bottom = M_STIMULUS_DISPLAY_BOTTOM_EDGE;
	}

	mprintf("Display bounds set to (%g left, %g right, %g top, %g bottom)",
			left, right, top, bottom);
}

void StimulusDisplay::getDisplayBounds(GLdouble &left, GLdouble &right, GLdouble &bottom, GLdouble &top) {
    left = this->left;
    right = this->right;
    bottom = this->bottom;
    top = this->top;
}

void StimulusDisplay::addContext(int _context_id){
	context_ids.push_back(_context_id);
	current_context_index = context_ids.size() - 1;
    opengl_context_manager->setCurrent(_context_id);

#ifdef RENDER_ONCE
    if (!(glewIsSupported("GL_EXT_framebuffer_object") && glewIsSupported("GL_EXT_framebuffer_blit"))) {
        throw SimpleException("renderer does not support required OpenGL framebuffer extensions");
    }
#endif
}

void StimulusDisplay::getCurrentViewportSize(GLint &width, GLint &height) {
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);
    width = viewport[2];
    height = viewport[3];
}

void StimulusDisplay::stateSystemCallback(const Datum &data, MWorksTime time) {
    boost::mutex::scoped_lock lock(display_lock);

    int newState = data.getInteger();

    if (IDLE == newState) {

        if (CVDisplayLinkIsRunning(displayLink)) {
            if (kCVReturnSuccess != CVDisplayLinkStop(displayLink)) {
                merror(M_DISPLAY_MESSAGE_DOMAIN, "Unable to stop display updates");
            } else {
                mprintf(M_DISPLAY_MESSAGE_DOMAIN, "Display updates stopped");
            }
        }

    } else if (RUNNING == newState) {

        if (!CVDisplayLinkIsRunning(displayLink)) {
            if (kCVReturnSuccess != CVDisplayLinkSetOutputCallback(displayLink,
                                                                   &StimulusDisplay::displayLinkCallback,
                                                                   this) ||
                kCVReturnSuccess != opengl_context_manager->prepareDisplayLinkForMainDisplay(displayLink) ||
                kCVReturnSuccess != CVDisplayLinkStart(displayLink))
            {
                merror(M_DISPLAY_MESSAGE_DOMAIN, "Unable to schedule display updates");
            } else {
                mprintf(M_DISPLAY_MESSAGE_DOMAIN,
                        "Display updates started (main = %d, current = %d)",
                        CGMainDisplayID(),
                        CVDisplayLinkGetCurrentCGDisplay(displayLink));
            }
        }

    }
}

CVReturn StimulusDisplay::displayLinkCallback(CVDisplayLinkRef _displayLink,
                                              const CVTimeStamp *now,
                                              const CVTimeStamp *outputTime,
                                              CVOptionFlags flagsIn,
                                              CVOptionFlags *flagsOut,
                                              void *_display)
{
    StimulusDisplay *display = static_cast<StimulusDisplay*>(_display);
    CVReturn status = kCVReturnSuccess;

    {
        boost::mutex::scoped_lock lock(display->display_lock);

        display->refreshDisplay();

//#define ERROR_ON_MISSED_REFRESH
#ifdef ERROR_ON_MISSED_REFRESH
        uint64_t currentTime = CVGetCurrentHostTime();
        if (currentTime > outputTime->hostTime) {
            merror(M_DISPLAY_MESSAGE_DOMAIN, "Display refresh did not complete within vertical blanking interval");
            status = kCVReturnError;
        }
#endif

        display->refreshComplete = true;
    }

    // Signal waiting threads that refresh is complete
    display->refreshCond.notify_all();

    return status;
}

void StimulusDisplay::refreshDisplay() {

    //
    // Draw stimuli on main display
    //

    MWTime before_draw = clock->getCurrentTimeUS();

    setCurrent(0);
    drawDisplayStack();

#define USE_GL_FENCE
#ifdef USE_GL_FENCE
    if(opengl_context_manager->hasFence()){
        glSetFenceAPPLE(opengl_context_manager->getFence());
    }
#endif

    opengl_context_manager->flush(0);

#ifdef USE_GL_FENCE
    if(opengl_context_manager->hasFence()){
        glFinishFenceAPPLE(opengl_context_manager->getFence());
    }
#endif

    MWTime now = clock->getCurrentTimeUS();
    stimDisplayUpdate->setValue(getAnnounceData(), now);
    announceDisplayStack(now);

#define ERROR_ON_LATE_FRAMES
#ifdef ERROR_ON_LATE_FRAMES
    int refresh_rate = opengl_context_manager->getDisplayRefreshRate(opengl_context_manager->getMainDisplayIndex());
    if(refresh_rate <= 0){
        refresh_rate = 60;
    }

    MWTime slop = 2*(1000000/refresh_rate);

    if(now-before_draw > slop) {
        merror(M_DISPLAY_MESSAGE_DOMAIN,
               "updating main window display is taking longer than two frames (%lld > %lld) to update",
               now-before_draw,
               slop);
    }
#endif

    //
    // Draw stimuli on mirror display(s)
    //

    if (context_ids.size() > 1) {
#ifndef RENDER_ONCE
        for (int i = 1; i < context_ids.size(); i++) {
            setCurrent(i);
            drawDisplayStack();
            opengl_context_manager->updateAndFlush(i);
        }
#else
        GLint srcWidth, srcHeight;
        getCurrentViewportSize(srcWidth, srcHeight);

        GLuint framebuffer, renderbuffer;
        glGenFramebuffersEXT(1, &framebuffer);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
        glGenRenderbuffersEXT(1, &renderbuffer);
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer);
        glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, srcWidth, srcHeight);
        glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, renderbuffer);

        GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
        if (GL_FRAMEBUFFER_COMPLETE_EXT != status) {
            merror(M_DISPLAY_MESSAGE_DOMAIN, "framebuffer setup failed (status = %d)", status);
            glDeleteRenderbuffersEXT(1, &renderbuffer);
            glDeleteFramebuffersEXT(1, &framebuffer);
            return;
        }

        glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
        glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer);
        glBlitFramebufferEXT(0, 0, srcWidth, srcHeight,
                             0, 0, srcWidth, srcHeight,
                             GL_COLOR_BUFFER_BIT,
                             GL_LINEAR);

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);  // Send subsequent rendering to back buffer

        for (int i = 1; i < context_ids.size(); i++) {
            setCurrent(i);

            GLint dstWidth, dstHeight;
            getCurrentViewportSize(dstWidth, dstHeight);

            glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer);
            glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
            glBlitFramebufferEXT(0, 0, srcWidth, srcHeight,
                                 0, 0, dstWidth, dstHeight,
                                 GL_COLOR_BUFFER_BIT,
                                 GL_LINEAR);

            opengl_context_manager->updateAndFlush(i);
        }

        glDeleteRenderbuffersEXT(1, &renderbuffer);
        glDeleteFramebuffersEXT(1, &framebuffer);
#endif /*RENDER_ONCE*/
    }
}

void StimulusDisplay::clearDisplay() {
    {
        boost::mutex::scoped_lock lock(display_lock);

        shared_ptr<StimulusNode> node = display_stack->getFrontmost();
        while(node) {
            node->setVisible(false);
            node = node->getNext();
        }
    }

	updateDisplay();
}

void StimulusDisplay::glInit() {

    glShadeModel(GL_FLAT);
    glDisable(GL_BLEND);
    glDisable(GL_DITHER);
    glDisable(GL_FOG);
    glDisable(GL_LIGHTING);

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); // DDC added

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity(); // Reset The Projection Matrix

    gluOrtho2D(left, right, bottom, top);
    glMatrixMode(GL_MODELVIEW);

    glClearColor(0.5, 0.5, 0.5, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

}

void StimulusDisplay::drawDisplayStack() {
    // OpenGL setup

    glInit();

    // Draw all of the stimuli in the chain, back to front

    shared_ptr<StimulusNode> node = display_stack->getBackmost();
    while (node) {
        if (node->isVisible()) {
            node->draw(shared_from_this());
        }
        node = node->getPrevious();
    }
}

void StimulusDisplay::updateDisplay() {
	boost::mutex::scoped_lock lock(display_lock);

    shared_ptr<StimulusNode> node = display_stack->getFrontmost();
    while (node) {
        if (node->isPending()) {
            // we're taking care of the pending state, so
            // clear this flag
            node->clearPending();

            // convert "pending visible" stimuli to "visible" ones
            node->setVisible(node->isPendingVisible());

            if (node->isPendingRemoval()) {
                node->clearPendingRemoval();
                node->remove();
                continue;
            }
        }

        node = node->getNext();
    }

    if (!CVDisplayLinkIsRunning(displayLink)) {
        // Need to do the refresh here
        refreshDisplay();
    } else {
        // Wait for next display refresh to complete
        refreshComplete = false;
        do {
            refreshCond.wait(lock);
        } while (!refreshComplete);
    }
}

void StimulusDisplay::announceDisplayStack(MWTime time) {
    shared_ptr<StimulusNode> node = display_stack->getBackmost(); //tail;

    while(node != shared_ptr< LinkedListNode<StimulusNode> >()) {
		if(node->isVisible()) {
            node->announceStimulusDraw(time);
		}

		node = node->getPrevious();
    }

}

Datum StimulusDisplay::getAnnounceData() {
    shared_ptr<StimulusNode> node = display_stack->getBackmost(); //tail;

    Datum stimAnnounce(M_LIST, 1);
    while(node != shared_ptr< LinkedListNode<StimulusNode> >()) {
		if(node->isVisible()) {
            Datum individualAnnounce(node->getCurrentAnnounceDrawData());
			if(!individualAnnounce.isUndefined()) {
				stimAnnounce.addElement(individualAnnounce);
			}
		}

		node = node->getPrevious();
    }
	return stimAnnounce;
}

<commit_msg>Minor tweak to StimulusDisplay<commit_after>/**
 * StimulusDisplay.cpp
 *
 * History:
 * Dave Cox on ??/??/?? - Created.
 * Paul Jankunas on 05/23/05 - Fixed spacing.
 *
 * Copyright 2005 MIT.  All rights reserved.
 */

#include "OpenGLContextManager.h"
#include "Stimulus.h"
#include "StimulusNode.h"
#include "Utilities.h"
#include "StandardVariables.h"
#include "Experiment.h"
#include "StandardVariables.h"
#include "ComponentRegistry.h"
#include "VariableNotification.h"

#include "boost/bind.hpp"

#ifdef	__APPLE__
	#include <AGL/agl.h>
	#include <OpenGL/gl.h>
	#include <OpenGL/glu.h>
    #include <CoreVideo/CVHostTime.h>
#elif	linux
	// TODO: where are these in linux?
#endif

#if M_OPENGL_SHARED_STATE == 1
    #define RENDER_ONCE
#endif

using namespace mw;

/**********************************************************************
 *                  StimulusDisplay Methods
 **********************************************************************/
StimulusDisplay::StimulusDisplay() {
    current_context_index = -1;

    // defer creation of the display chain until after the stimulus display has been created
    display_stack = shared_ptr< LinkedList<StimulusNode> >(new LinkedList<StimulusNode>());

	setDisplayBounds();

    opengl_context_manager = OpenGLContextManager::instance();
    clock = Clock::instance();

    if (kCVReturnSuccess != CVDisplayLinkCreateWithActiveCGDisplays(&displayLink)) {
        throw SimpleException("Unable to create display link");
    }

    stateSystemNotification = shared_ptr<VariableCallbackNotification>(new VariableCallbackNotification(boost::bind(&StimulusDisplay::stateSystemCallback, this, _1, _2)));
    state_system_mode->addNotification(stateSystemNotification);
}

StimulusDisplay::~StimulusDisplay(){
    stateSystemNotification->remove();
    CVDisplayLinkRelease(displayLink);
}

void StimulusDisplay::setCurrent(int i){
    if ((i >= getNContexts()) || (i < 0)) {
        merror(M_DISPLAY_MESSAGE_DOMAIN, "invalid context index (%d)", i);
        return;
    }

	current_context_index = i;
	opengl_context_manager->setCurrent(context_ids[i]);
}

shared_ptr<StimulusNode> StimulusDisplay::addStimulus(shared_ptr<Stimulus> stim) {
    if(!stim) {
        mprintf("Attempt to load NULL stimulus");
        return shared_ptr<StimulusNode>();
    }

	shared_ptr<StimulusNode> stimnode(new StimulusNode(stim));

    display_stack->addToFront(stimnode);

	return stimnode;
}

void StimulusDisplay::addStimulusNode(shared_ptr<StimulusNode> stimnode) {
    if(!stimnode) {
        mprintf("Attempt to load NULL stimulus");
        return;
    }

	// remove it, in case it already belongs to a list
	stimnode->remove();

	display_stack->addToFront(stimnode);  // TODO
}

void StimulusDisplay::setDisplayBounds(){
  shared_ptr<mw::ComponentRegistry> reg = mw::ComponentRegistry::getSharedRegistry();
  shared_ptr<Variable> main_screen_info = reg->getVariable(MAIN_SCREEN_INFO_TAGNAME);

 Datum display_info = *main_screen_info; // from standard variables
	if(display_info.getDataType() == M_DICTIONARY &&
	   display_info.hasKey(M_DISPLAY_WIDTH_KEY) &&
	   display_info.hasKey(M_DISPLAY_HEIGHT_KEY) &&
	   display_info.hasKey(M_DISPLAY_DISTANCE_KEY)){

		GLdouble width_unknown_units = display_info.getElement(M_DISPLAY_WIDTH_KEY);
		GLdouble height_unknown_units = display_info.getElement(M_DISPLAY_HEIGHT_KEY);
		GLdouble distance_unknown_units = display_info.getElement(M_DISPLAY_DISTANCE_KEY);

		GLdouble half_width_deg = (180. / M_PI) * atan((width_unknown_units/2.)/distance_unknown_units);
		GLdouble half_height_deg = half_width_deg * height_unknown_units / width_unknown_units;
		//GLdouble half_height_deg = (180. / M_PI) * atan((height_unknown_units/2.)/distance_unknown_units);

		left = -half_width_deg;
		right = half_width_deg;
		top = half_height_deg;
		bottom = -half_height_deg;
	} else {
		left = M_STIMULUS_DISPLAY_LEFT_EDGE;
		right = M_STIMULUS_DISPLAY_RIGHT_EDGE;
		top = M_STIMULUS_DISPLAY_TOP_EDGE;
		bottom = M_STIMULUS_DISPLAY_BOTTOM_EDGE;
	}

	mprintf("Display bounds set to (%g left, %g right, %g top, %g bottom)",
			left, right, top, bottom);
}

void StimulusDisplay::getDisplayBounds(GLdouble &left, GLdouble &right, GLdouble &bottom, GLdouble &top) {
    left = this->left;
    right = this->right;
    bottom = this->bottom;
    top = this->top;
}

void StimulusDisplay::addContext(int _context_id){
	context_ids.push_back(_context_id);
	current_context_index = context_ids.size() - 1;
    opengl_context_manager->setCurrent(_context_id);

#ifdef RENDER_ONCE
    if (!(glewIsSupported("GL_EXT_framebuffer_object") && glewIsSupported("GL_EXT_framebuffer_blit"))) {
        throw SimpleException("renderer does not support required OpenGL framebuffer extensions");
    }
#endif
}

void StimulusDisplay::getCurrentViewportSize(GLint &width, GLint &height) {
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);
    width = viewport[2];
    height = viewport[3];
}

void StimulusDisplay::stateSystemCallback(const Datum &data, MWorksTime time) {
    boost::mutex::scoped_lock lock(display_lock);

    int newState = data.getInteger();

    if (IDLE == newState) {

        if (CVDisplayLinkIsRunning(displayLink)) {
            if (kCVReturnSuccess != CVDisplayLinkStop(displayLink)) {
                merror(M_DISPLAY_MESSAGE_DOMAIN, "Unable to stop display updates");
            } else {
                mprintf(M_DISPLAY_MESSAGE_DOMAIN, "Display updates stopped");
            }
        }

    } else if (RUNNING == newState) {

        if (!CVDisplayLinkIsRunning(displayLink)) {
            if (kCVReturnSuccess != CVDisplayLinkSetOutputCallback(displayLink,
                                                                   &StimulusDisplay::displayLinkCallback,
                                                                   this) ||
                kCVReturnSuccess != opengl_context_manager->prepareDisplayLinkForMainDisplay(displayLink) ||
                kCVReturnSuccess != CVDisplayLinkStart(displayLink))
            {
                merror(M_DISPLAY_MESSAGE_DOMAIN, "Unable to schedule display updates");
            } else {
                mprintf(M_DISPLAY_MESSAGE_DOMAIN,
                        "Display updates started (main = %d, current = %d)",
                        CGMainDisplayID(),
                        CVDisplayLinkGetCurrentCGDisplay(displayLink));
            }
        }

    }
}

CVReturn StimulusDisplay::displayLinkCallback(CVDisplayLinkRef _displayLink,
                                              const CVTimeStamp *now,
                                              const CVTimeStamp *outputTime,
                                              CVOptionFlags flagsIn,
                                              CVOptionFlags *flagsOut,
                                              void *_display)
{
    StimulusDisplay *display = static_cast<StimulusDisplay*>(_display);
    CVReturn status = kCVReturnSuccess;

    {
        boost::mutex::scoped_lock lock(display->display_lock);

        display->refreshDisplay();

//#define ERROR_ON_MISSED_REFRESH
#ifdef ERROR_ON_MISSED_REFRESH
        uint64_t currentTime = CVGetCurrentHostTime();
        if (currentTime > outputTime->hostTime) {
            merror(M_DISPLAY_MESSAGE_DOMAIN, "Display refresh did not complete within vertical blanking interval");
            status = kCVReturnError;
        }
#endif

        display->refreshComplete = true;
    }

    // Signal waiting threads that refresh is complete
    display->refreshCond.notify_all();

    return status;
}

void StimulusDisplay::refreshDisplay() {

    //
    // Draw stimuli on main display
    //

    MWTime before_draw = clock->getCurrentTimeUS();

    setCurrent(0);
    drawDisplayStack();

#define USE_GL_FENCE
#ifdef USE_GL_FENCE
    if(opengl_context_manager->hasFence()){
        glSetFenceAPPLE(opengl_context_manager->getFence());
    }
#endif

    opengl_context_manager->flush(0);

#ifdef USE_GL_FENCE
    if(opengl_context_manager->hasFence()){
        glFinishFenceAPPLE(opengl_context_manager->getFence());
    }
#endif

    MWTime now = clock->getCurrentTimeUS();
    stimDisplayUpdate->setValue(getAnnounceData(), now);
    announceDisplayStack(now);

#define ERROR_ON_LATE_FRAMES
#ifdef ERROR_ON_LATE_FRAMES
    int refresh_rate = opengl_context_manager->getDisplayRefreshRate(opengl_context_manager->getMainDisplayIndex());
    if(refresh_rate <= 0){
        refresh_rate = 60;
    }

    MWTime slop = 2*(1000000/refresh_rate);

    if(now-before_draw > slop) {
        merror(M_DISPLAY_MESSAGE_DOMAIN,
               "updating main window display is taking longer than two frames (%lld > %lld) to update",
               now-before_draw,
               slop);
    }
#endif

    //
    // Draw stimuli on mirror display(s)
    //

#ifndef RENDER_ONCE
    for (int i = 1; i < context_ids.size(); i++) {
        setCurrent(i);
        drawDisplayStack();
        opengl_context_manager->updateAndFlush(i);
    }
#else
    if (context_ids.size() > 1) {
        GLint srcWidth, srcHeight;
        getCurrentViewportSize(srcWidth, srcHeight);

        GLuint framebuffer, renderbuffer;
        glGenFramebuffersEXT(1, &framebuffer);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
        glGenRenderbuffersEXT(1, &renderbuffer);
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer);
        glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, srcWidth, srcHeight);
        glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, renderbuffer);

        GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
        if (GL_FRAMEBUFFER_COMPLETE_EXT != status) {
            merror(M_DISPLAY_MESSAGE_DOMAIN, "framebuffer setup failed (status = %d)", status);
            glDeleteRenderbuffersEXT(1, &renderbuffer);
            glDeleteFramebuffersEXT(1, &framebuffer);
            return;
        }

        glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
        glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer);
        glBlitFramebufferEXT(0, 0, srcWidth, srcHeight,
                             0, 0, srcWidth, srcHeight,
                             GL_COLOR_BUFFER_BIT,
                             GL_LINEAR);

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);  // Send subsequent rendering to back buffer

        for (int i = 1; i < context_ids.size(); i++) {
            setCurrent(i);

            GLint dstWidth, dstHeight;
            getCurrentViewportSize(dstWidth, dstHeight);

            glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer);
            glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
            glBlitFramebufferEXT(0, 0, srcWidth, srcHeight,
                                 0, 0, dstWidth, dstHeight,
                                 GL_COLOR_BUFFER_BIT,
                                 GL_LINEAR);

            opengl_context_manager->updateAndFlush(i);
        }

        glDeleteRenderbuffersEXT(1, &renderbuffer);
        glDeleteFramebuffersEXT(1, &framebuffer);
    }
#endif /*RENDER_ONCE*/
}

void StimulusDisplay::clearDisplay() {
    {
        boost::mutex::scoped_lock lock(display_lock);

        shared_ptr<StimulusNode> node = display_stack->getFrontmost();
        while(node) {
            node->setVisible(false);
            node = node->getNext();
        }
    }

	updateDisplay();
}

void StimulusDisplay::glInit() {

    glShadeModel(GL_FLAT);
    glDisable(GL_BLEND);
    glDisable(GL_DITHER);
    glDisable(GL_FOG);
    glDisable(GL_LIGHTING);

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); // DDC added

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity(); // Reset The Projection Matrix

    gluOrtho2D(left, right, bottom, top);
    glMatrixMode(GL_MODELVIEW);

    glClearColor(0.5, 0.5, 0.5, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

}

void StimulusDisplay::drawDisplayStack() {
    // OpenGL setup

    glInit();

    // Draw all of the stimuli in the chain, back to front

    shared_ptr<StimulusNode> node = display_stack->getBackmost();
    while (node) {
        if (node->isVisible()) {
            node->draw(shared_from_this());
        }
        node = node->getPrevious();
    }
}

void StimulusDisplay::updateDisplay() {
	boost::mutex::scoped_lock lock(display_lock);

    shared_ptr<StimulusNode> node = display_stack->getFrontmost();
    while (node) {
        if (node->isPending()) {
            // we're taking care of the pending state, so
            // clear this flag
            node->clearPending();

            // convert "pending visible" stimuli to "visible" ones
            node->setVisible(node->isPendingVisible());

            if (node->isPendingRemoval()) {
                node->clearPendingRemoval();
                node->remove();
                continue;
            }
        }

        node = node->getNext();
    }

    if (!CVDisplayLinkIsRunning(displayLink)) {
        // Need to do the refresh here
        refreshDisplay();
    } else {
        // Wait for next display refresh to complete
        refreshComplete = false;
        do {
            refreshCond.wait(lock);
        } while (!refreshComplete);
    }
}

void StimulusDisplay::announceDisplayStack(MWTime time) {
    shared_ptr<StimulusNode> node = display_stack->getBackmost(); //tail;

    while(node != shared_ptr< LinkedListNode<StimulusNode> >()) {
		if(node->isVisible()) {
            node->announceStimulusDraw(time);
		}

		node = node->getPrevious();
    }

}

Datum StimulusDisplay::getAnnounceData() {
    shared_ptr<StimulusNode> node = display_stack->getBackmost(); //tail;

    Datum stimAnnounce(M_LIST, 1);
    while(node != shared_ptr< LinkedListNode<StimulusNode> >()) {
		if(node->isVisible()) {
            Datum individualAnnounce(node->getCurrentAnnounceDrawData());
			if(!individualAnnounce.isUndefined()) {
				stimAnnounce.addElement(individualAnnounce);
			}
		}

		node = node->getPrevious();
    }
	return stimAnnounce;
}

<|endoftext|>


<commit_before>/**
 * @file Cosa/Pins.cpp
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2012, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * @section Description
 * Arduino pins abstractions; abstract, input, output, interrupt and
 * analog pin. Captures the mapping from Arduino to processor pins.
 * Forces declarative programming of pins in sketches.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#include "Cosa/Pins.h"
#include <util/delay_basic.h>

#define DELAY(us) _delay_loop_2((us) << 2)

uint8_t
Pin::await_change(uint8_t us)
{
  uint8_t res = 0;
  synchronized {
    if (is_set()) {
      while (is_set() && us--) res++;
    }
    else {
      while (is_clear() && us--) res++;
    }
  }
  return (res);
}

void
Pin::print(IOStream& stream)
{
  stream.printf_P(PSTR("Pin(pin = %d, sfr = %p, mask = %bd)"),
		  _pin, _sfr, _mask);
}

void
Pin::println(IOStream& stream)
{
  print();
  stream.println();
}

InterruptPin* InterruptPin::ext[2] = { 0, 0 };

ISR(INT0_vect)
{
  if (InterruptPin::ext[0] != 0)
    InterruptPin::ext[0]->on_interrupt();
}

ISR(INT1_vect)
{
  if (InterruptPin::ext[1] != 0)
    InterruptPin::ext[1]->on_interrupt();
}

void
OutputPin::pulse(uint16_t us)
{
  toggle();
  DELAY(us);
  toggle();
}

void
PWMPin::set(uint8_t duty)
{
  if (_pin == 3) {
    bit_set(TCCR2A, COM2A1);
    OCR2A = duty;
    return;
  }
  if (_pin == 5) {
    bit_set(TCCR0A, COM0B1);
    OCR0B = duty;
    return;
  }
  if (_pin == 6) {
    bit_set(TCCR0A, COM0A1);
    OCR0A = duty;
    return;
  }
  if (_pin == 11) {
    bit_set(TCCR2A, COM2B1);
    OCR2B = duty;
    return;
  }
  if (duty < 128)
    OutputPin::clear();
  else
    OutputPin::set();
}

void
PWMPin::set(uint16_t value, uint16_t min, uint16_t max)
{
  uint8_t duty;
  if (value <= min) duty = 0;
  else if (value >= max) duty = 255;
  else duty = (((uint32_t) (value - min)) << 8) / (max - min);
  set(duty);
}

uint8_t
PWMPin::get_duty()
{
  if (_pin == 5) return (OCR0B);
  if (_pin == 6) return (OCR0A);
  return (is_set());
}

AnalogPin* AnalogPin::sampling_pin = 0;

uint16_t
AnalogPin::sample()
{
  loop_until_bit_is_clear(ADCSRA, ADSC);
  ADMUX = (_reference | ((_pin - 14) & 0xf));
  bit_mask_set(ADCSRA, _BV(ADEN) | _BV(ADSC));
  loop_until_bit_is_clear(ADCSRA, ADSC);
  return (_value = ADCW);
}

void
AnalogPin::sample_request()
{
  loop_until_bit_is_clear(ADCSRA, ADSC);
  ADMUX = (_reference | (_pin - 14));
  bit_mask_set(ADCSRA, _BV(ADEN) | _BV(ADSC));
  if (_handler == 0) return;
  sampling_pin = this;
  bit_set(ADCSRA, ADIE);
}

uint16_t
AnalogPin::sample_await()
{
  loop_until_bit_is_clear(ADCSRA, ADSC);
  return (_value = ADCW);
}

ISR(ADC_vect)
{
  bit_clear(ADCSRA, ADIE);
  AnalogPin* pin = AnalogPin::get_sampling_pin();
  if (pin != 0) pin->on_sample(ADCW);
}

void
AnalogPins::sample_next(AnalogPin* pin, void* env)
{
  AnalogPins* set = (AnalogPins*) env;
  if (set->_next != set->_count) {
    AnalogPin* pin = set->get_pin_at(set->_next++);
    pin->sample_request();
  }
  else if (set->_handler != 0) {
    set->_handler(set, set->_env);
  }
}

bool
AnalogPins::samples_request(InterruptHandler fn, void* env)
{
  if (AnalogPin::get_sampling_pin() != 0) return (0);
  if (fn != 0) {
    _handler = fn;
    _env = env;
  }
  get_pin_at(0)->sample_request();
  _next = 1;
  return (1);
}

<commit_msg>Fixed PWMPin 3/11. Pins where switched.<commit_after>/**
 * @file Cosa/Pins.cpp
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2012, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * @section Description
 * Arduino pins abstractions; abstract, input, output, interrupt and
 * analog pin. Captures the mapping from Arduino to processor pins.
 * Forces declarative programming of pins in sketches.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#include "Cosa/Pins.h"
#include <util/delay_basic.h>

#define DELAY(us) _delay_loop_2((us) << 2)

uint8_t
Pin::await_change(uint8_t us)
{
  uint8_t res = 0;
  synchronized {
    if (is_set()) {
      while (is_set() && us--) res++;
    }
    else {
      while (is_clear() && us--) res++;
    }
  }
  return (res);
}

void
Pin::print(IOStream& stream)
{
  stream.printf_P(PSTR("Pin(pin = %d, sfr = %p, mask = %bd)"),
		  _pin, _sfr, _mask);
}

void
Pin::println(IOStream& stream)
{
  print();
  stream.println();
}

InterruptPin* InterruptPin::ext[2] = { 0, 0 };

ISR(INT0_vect)
{
  if (InterruptPin::ext[0] != 0)
    InterruptPin::ext[0]->on_interrupt();
}

ISR(INT1_vect)
{
  if (InterruptPin::ext[1] != 0)
    InterruptPin::ext[1]->on_interrupt();
}

void
OutputPin::pulse(uint16_t us)
{
  toggle();
  DELAY(us);
  toggle();
}

void
PWMPin::set(uint8_t duty)
{
  if (_pin == 3) {
    bit_set(TCCR2A, COM2B1);
    OCR2B = duty;
    return;
  }
  if (_pin == 5) {
    bit_set(TCCR0A, COM0B1);
    OCR0B = duty;
    return;
  }
  if (_pin == 6) {
    bit_set(TCCR0A, COM0A1);
    OCR0A = duty;
    return;
  }
  if (_pin == 11) {
    bit_set(TCCR2A, COM2A1);
    OCR2A = duty;
    return;
  }
  if (duty < 128)
    OutputPin::clear();
  else
    OutputPin::set();
}

void
PWMPin::set(uint16_t value, uint16_t min, uint16_t max)
{
  uint8_t duty;
  if (value <= min) duty = 0;
  else if (value >= max) duty = 255;
  else duty = (((uint32_t) (value - min)) << 8) / (max - min);
  set(duty);
}

uint8_t
PWMPin::get_duty()
{
  if (_pin == 5) return (OCR0B);
  if (_pin == 6) return (OCR0A);
  return (is_set());
}

AnalogPin* AnalogPin::sampling_pin = 0;

uint16_t
AnalogPin::sample()
{
  loop_until_bit_is_clear(ADCSRA, ADSC);
  ADMUX = (_reference | ((_pin - 14) & 0xf));
  bit_mask_set(ADCSRA, _BV(ADEN) | _BV(ADSC));
  loop_until_bit_is_clear(ADCSRA, ADSC);
  return (_value = ADCW);
}

void
AnalogPin::sample_request()
{
  loop_until_bit_is_clear(ADCSRA, ADSC);
  ADMUX = (_reference | (_pin - 14));
  bit_mask_set(ADCSRA, _BV(ADEN) | _BV(ADSC));
  if (_handler == 0) return;
  sampling_pin = this;
  bit_set(ADCSRA, ADIE);
}

uint16_t
AnalogPin::sample_await()
{
  loop_until_bit_is_clear(ADCSRA, ADSC);
  return (_value = ADCW);
}

ISR(ADC_vect)
{
  bit_clear(ADCSRA, ADIE);
  AnalogPin* pin = AnalogPin::get_sampling_pin();
  if (pin != 0) pin->on_sample(ADCW);
}

void
AnalogPins::sample_next(AnalogPin* pin, void* env)
{
  AnalogPins* set = (AnalogPins*) env;
  if (set->_next != set->_count) {
    AnalogPin* pin = set->get_pin_at(set->_next++);
    pin->sample_request();
  }
  else if (set->_handler != 0) {
    set->_handler(set, set->_env);
  }
}

bool
AnalogPins::samples_request(InterruptHandler fn, void* env)
{
  if (AnalogPin::get_sampling_pin() != 0) return (0);
  if (fn != 0) {
    _handler = fn;
    _env = env;
  }
  get_pin_at(0)->sample_request();
  _next = 1;
  return (1);
}

<|endoftext|>


<commit_before>#include <algorithm>
#include <unordered_map>
#include <string>
#include <thread>
#include <iostream>

#include "message.h"
#include "message_pipe.h"
#include "registry.h"
#include "plugin_loader.h"
#include "required_messages.h"
#include "core_messages.h"

using namespace std;

static unordered_map<string, message_pipe> out_pipes;
static unordered_map<string, registry> message_registrations;
static message_pipe in_pipe;

static bool verbose;

ostream &operator<<(ostream &out, const message &m)
{
	return out << '(' << m.type << ',' << m.priority << ',' << m.getdata() << ')';
}

static void to_plugin(message m)
{
	if (message_registrations.count(m.gettype())==0)
	{
		//This message type has no registration, so discard it
		if (verbose)
			cerr << " was not registered" << endl;
		return;
	}
	auto plugin=message_registrations[m.gettype()].get(m.getpriority());
	if (plugin.second=="")
	{
		if (verbose)
			cerr << " has no more registered plugins" << endl;
		return;
	}
	if (out_pipes.count(plugin.second)==0)
	{
		//This type does not exist
		if (verbose)
			cerr << " is registered to the non-existent plugin " << plugin.second << endl;
		return;
	}
	//Change the message priority to the registered priority
	out_pipes[plugin.second].write(m.change_priority(plugin.first));
	if (verbose)
		cerr << " was sent to " << plugin.second << " as " << m << endl;
}

static void add_plugin(const message &m)
{
	auto pa=dynamic_cast<plugin_adder *>(m.getdata());
	if (!pa)
		//The message wasn't a plugin_adder
		return;
	if (out_pipes.count(pa->name)!=0)
		//There's already a plugin with this name
		return;
	message_pipe mp;
	thread t1(load_plugin, pa->filename, plugin_pipe(bidirectional_message_pipe(mp, in_pipe)));
	t1.detach();
	out_pipes[pa->name]=mp;
	mp.write(hello_message::create(pa->name));
	if (verbose)
		cerr << " loaded plugin " << pa->name << " from " << pa->filename << endl;
}

static void remove_plugin(const message &m)
{
	auto d=dynamic_cast<done_message *>(m.getdata());
	if (!d)
		return;
	for (auto &i : message_registrations)
		i.second.removeall(d->name);
	decltype(message_registrations.begin()) i;
	//Who says C++ is verbose?
	while ((i=std::find_if(message_registrations.begin(), message_registrations.end(), [](decltype(*i) &p) {return p.second.empty();}))!=message_registrations.end())
			message_registrations.erase(i);
	out_pipes.erase(d->name);
	if (verbose)
		cerr << " removed plugin " << d->name << endl;
}

static void add_registration(const message &m)
{
	auto r=dynamic_cast<registration_message *>(m.getdata());
	if (!r)
		return;
	if (out_pipes.count(r->getname())==0)
		//We can't talk to this plugin, so ignore its request
		return;

	bool b=message_registrations[r->getmessage()].add(r->getpriority(), r->getname());
	//Tell the plugin whether it failed or not
	out_pipes[r->getname()].write(registration_status::create(b, r->getpriority(), r->getmessage()));
	if (verbose)
		cerr << " registered " << r->message_type << " to " << r->plugin_name << endl;
}

static void target_plugin(const message &m)
{
	auto i=dynamic_cast<targeted_message *>(m.getdata());
	if (!i)
		return;
	if (out_pipes.count(i->name)==0)
		return;
	out_pipes[i->name].write(i->mess);
	if (verbose)
		cerr << " targeted " << i->mess << " towards " << i->name << endl;
}

static void process(const message &m)
{
	if (verbose)
		cerr << "Message " << m;
	if (m.gettype()=="add_plugin")
		add_plugin(m);
	else if (m.gettype()=="register")
		add_registration(m);
	else if (m.type=="done")
		remove_plugin(m);
	else if (m.type=="target")
		target_plugin(m);
	else
		to_plugin(m);
}

static void run_core(const vector<message> &vm)
{
	for (auto m : vm)
		process(m);
	while (!out_pipes.empty())
	{
		process(in_pipe.blocking_read());
	}
}

int main(int argc, char *argv[])
{
	vector<message> vm;
	for (int i=1; i<argc-1; i+=2)
	{
		if (argv[i]==string("-v") || argv[i]==string("--verbose"))
		{
			verbose=true;
			--i;
		}
		else
			vm.push_back(plugin_adder::create(argv[i],argv[i+1]));
	}
	run_core(vm);
}
<commit_msg>Use the system locale instead of the default C locale<commit_after>#include <algorithm>
#include <unordered_map>
#include <string>
#include <thread>
#include <iostream>

#include "message.h"
#include "message_pipe.h"
#include "registry.h"
#include "plugin_loader.h"
#include "required_messages.h"
#include "core_messages.h"

using namespace std;

static unordered_map<string, message_pipe> out_pipes;
static unordered_map<string, registry> message_registrations;
static message_pipe in_pipe;

static bool verbose;

ostream &operator<<(ostream &out, const message &m)
{
	return out << '(' << m.type << ',' << m.priority << ',' << m.getdata() << ')';
}

static void to_plugin(message m)
{
	if (message_registrations.count(m.gettype())==0)
	{
		//This message type has no registration, so discard it
		if (verbose)
			cerr << " was not registered" << endl;
		return;
	}
	auto plugin=message_registrations[m.gettype()].get(m.getpriority());
	if (plugin.second=="")
	{
		if (verbose)
			cerr << " has no more registered plugins" << endl;
		return;
	}
	if (out_pipes.count(plugin.second)==0)
	{
		//This type does not exist
		if (verbose)
			cerr << " is registered to the non-existent plugin " << plugin.second << endl;
		return;
	}
	//Change the message priority to the registered priority
	out_pipes[plugin.second].write(m.change_priority(plugin.first));
	if (verbose)
		cerr << " was sent to " << plugin.second << " as " << m << endl;
}

static void add_plugin(const message &m)
{
	auto pa=dynamic_cast<plugin_adder *>(m.getdata());
	if (!pa)
		//The message wasn't a plugin_adder
		return;
	if (out_pipes.count(pa->name)!=0)
		//There's already a plugin with this name
		return;
	message_pipe mp;
	thread t1(load_plugin, pa->filename, plugin_pipe(bidirectional_message_pipe(mp, in_pipe)));
	t1.detach();
	out_pipes[pa->name]=mp;
	mp.write(hello_message::create(pa->name));
	if (verbose)
		cerr << " loaded plugin " << pa->name << " from " << pa->filename << endl;
}

static void remove_plugin(const message &m)
{
	auto d=dynamic_cast<done_message *>(m.getdata());
	if (!d)
		return;
	for (auto &i : message_registrations)
		i.second.removeall(d->name);
	decltype(message_registrations.begin()) i;
	//Who says C++ is verbose?
	while ((i=std::find_if(message_registrations.begin(), message_registrations.end(), [](decltype(*i) &p) {return p.second.empty();}))!=message_registrations.end())
			message_registrations.erase(i);
	out_pipes.erase(d->name);
	if (verbose)
		cerr << " removed plugin " << d->name << endl;
}

static void add_registration(const message &m)
{
	auto r=dynamic_cast<registration_message *>(m.getdata());
	if (!r)
		return;
	if (out_pipes.count(r->getname())==0)
		//We can't talk to this plugin, so ignore its request
		return;

	bool b=message_registrations[r->getmessage()].add(r->getpriority(), r->getname());
	//Tell the plugin whether it failed or not
	out_pipes[r->getname()].write(registration_status::create(b, r->getpriority(), r->getmessage()));
	if (verbose)
		cerr << " registered " << r->message_type << " to " << r->plugin_name << endl;
}

static void target_plugin(const message &m)
{
	auto i=dynamic_cast<targeted_message *>(m.getdata());
	if (!i)
		return;
	if (out_pipes.count(i->name)==0)
		return;
	out_pipes[i->name].write(i->mess);
	if (verbose)
		cerr << " targeted " << i->mess << " towards " << i->name << endl;
}

static void process(const message &m)
{
	if (verbose)
		cerr << "Message " << m;
	if (m.gettype()=="add_plugin")
		add_plugin(m);
	else if (m.gettype()=="register")
		add_registration(m);
	else if (m.type=="done")
		remove_plugin(m);
	else if (m.type=="target")
		target_plugin(m);
	else
		to_plugin(m);
}

static void run_core(const vector<message> &vm)
{
	for (auto m : vm)
		process(m);
	while (!out_pipes.empty())
	{
		process(in_pipe.blocking_read());
	}
}

int main(int argc, char *argv[])
{
	setlocale(LC_ALL,"");
	vector<message> vm;
	for (int i=1; i<argc-1; i+=2)
	{
		if (argv[i]==string("-v") || argv[i]==string("--verbose"))
		{
			verbose=true;
			--i;
		}
		else
			vm.push_back(plugin_adder::create(argv[i],argv[i+1]));
	}
	run_core(vm);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "stdafx.h"
#include "config.h"

#include "WebFrame.h"
#include "WebFramePrivate.h"
#include "WebView.h"
#include "WebHost.h"

#include "Document.h"
#include "FrameView.h"
#include "FrameWin.h"
#include "GraphicsContext.h"
#include "Page.h"
#include "render_frames.h"
#include "cairo.h"
#include "cairo-win32.h"
#include "TransferJob.h"

#include <io.h>
#include <fcntl.h>
#include <direct.h>
#include <WinInet.h>

using namespace WebCore;

namespace WebKit {

class WebFramePrivate::WebFrameData {
public:
    WebFrameData() { }
    ~WebFrameData() { }

    RefPtr<Frame> frame;
    RefPtr<FrameView> frameView;
    WebView* webView;
    WebHost* m_host;};

WebFramePrivate::WebFramePrivate(char* name, WebView* view, WebHost* host)
: d(new WebFramePrivate::WebFrameData)
{
    d->m_host = host;
    d->webView = view;
    Page* page = new Page();
    Frame* frame = new FrameWin(page, 0, this);
    d->frame = frame;
    frame->deref(); // Frames are created with a refcount of 1.  Release this ref, since we've assigned it to a RefPtr
    page->setMainFrame(frame);
    FrameView* frameView = new FrameView(frame);
    d->frameView = frameView;
    frameView->deref(); // FrameViews are created with a refcount of 1.  Release this ref, since we've assigned it to a RefPtr
    d->frame->setView(frameView);
    d->frameView->setWindowHandle(view->windowHandle());
}

WebFramePrivate::~WebFramePrivate()
{
    delete d->frame->page();
    delete d;
}

void WebFramePrivate::loadFilePath(char* path)
{
    char URL[2048];
    strcpy(URL, "file://localhost/");
    strncat(URL, path, 2020);

    d->frame->didOpenURL(URL);
    d->frame->begin(URL);
    HANDLE fileHandle = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    bool result = false;
    DWORD bytesRead = 0;

    do {
      const int bufferSize = 8193;
      char buffer[bufferSize];
      result = ReadFile(fileHandle, &buffer, bufferSize - 1, &bytesRead, NULL);
      buffer[bytesRead] = '\0';
      d->frame->write(buffer);
      // Check for end of file.
    } while (result && bytesRead);

    CloseHandle(fileHandle);

    d->frame->end();
}

void WebFramePrivate::loadHTMLString(char *html, char *baseURL)
{
    d->frame->begin();
    d->frame->write(html);
    d->frame->end();
}

void WebFramePrivate::openURL(const DeprecatedString& str)
{
    loadURL(str.ascii());
}

void WebFramePrivate::submitForm(const String& method, const KURL& url, const FormData* submitFormData)
{
    // FIXME: This is a dumb implementation, doesn't handle subframes, etc.
    d->frame->didOpenURL(url);
    d->frame->begin(url);
    TransferJob* job;
    if (method == "GET" || !submitFormData)
        job = new TransferJob(this, method, url);
    else
        job = new TransferJob(this, method, url, *submitFormData);
    job->start(d->frame->document()->docLoader());
    if (d->m_host) {
        DeprecatedCString urlString = url.prettyURL().utf8();
        d->m_host->updateLocationBar(urlString);
    }
}

void WebFramePrivate::loadURL(const char* URL)
{
    d->frame->didOpenURL(URL);
    d->frame->begin(URL);
    WebCore::TransferJob* job = new TransferJob(this, "GET", URL);
    job->start(d->frame->document()->docLoader());
    if (d->m_host)
        d->m_host->updateLocationBar(URL);
}

void WebFramePrivate::getURL(char* url, int length)
{
    if (length <= 0)
        return;
    *url = 0;

    DeprecatedCString urlString = d->frame->url().prettyURL().utf8();
    const char* srcURL = urlString;
    if (srcURL) {
        int srcURLLength = strlen(srcURL);
        if (length > srcURLLength)
            strcpy(url, srcURL);
    }
}

void WebFramePrivate::reload()
{
    if (!d->frame->url().url().startsWith("javascript:", false))
        d->frame->scheduleLocationChange(d->frame->url().url(), d->frame->referrer(), true/*lock history*/, true/*userGesture*/);
}

void WebFramePrivate::receivedData(WebCore::TransferJob*, const char* data, int length)
{
    d->frame->write(data, length);
}

void WebFramePrivate::receivedAllData(WebCore::TransferJob* job, WebCore::PlatformData)
{
    d->frame->end();
}

void WebFramePrivate::paint()
{
    d->frameView->layout();

    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(d->webView->windowHandle(), &ps);
    cairo_surface_t* finalSurface = cairo_win32_surface_create(hdc);
    cairo_surface_t* surface = cairo_surface_create_similar(finalSurface,
                                                            CAIRO_CONTENT_COLOR_ALPHA,
                                                            ps.rcPaint.right, ps.rcPaint.bottom);

    cairo_t* context = cairo_create(surface);
    GraphicsContext gc(context);

    IntRect documentDirtyRect = ps.rcPaint;
    documentDirtyRect.move(d->frameView->contentsX(), d->frameView->contentsY());

    // FIXME: We have to set the transform using both cairo and GDI until we use cairo for text.
    HDC surfaceDC = cairo_win32_surface_get_dc(surface);
    SaveDC(surfaceDC);
    OffsetViewportOrgEx(surfaceDC, -d->frameView->contentsX(), -d->frameView->contentsY(), 0);
    cairo_translate(context, -d->frameView->contentsX(), -d->frameView->contentsY());
    d->frame->paint(&gc, documentDirtyRect);
    RestoreDC(surfaceDC, -1);

    cairo_destroy(context);
    context = cairo_create(finalSurface);
    cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
    cairo_set_source_surface(context, surface, 0, 0);
    cairo_rectangle(context, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom);
    cairo_fill(context);
    cairo_destroy(context);

    cairo_surface_destroy(surface);
    cairo_surface_destroy(finalSurface);

    EndPaint(d->webView->windowHandle(), &ps);
}

WebCore::Frame* WebFramePrivate::impl()
{
    return d->frame.get();
}

WebFramePrivate* WebFramePrivate::toPrivate()
{
    return this;
}

}

<commit_msg>2006-05-01  Steve Falkenburg  <sfalken@apple.com><commit_after>/*
 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "stdafx.h"
#include "config.h"

#include "WebFrame.h"
#include "WebFramePrivate.h"
#include "WebView.h"
#include "WebHost.h"

#include "Document.h"
#include "FrameView.h"
#include "FrameWin.h"
#include "GraphicsContext.h"
#include "Page.h"
#include "render_frames.h"
#include "cairo.h"
#include "cairo-win32.h"
#include "TransferJob.h"

#include <io.h>
#include <fcntl.h>
#include <direct.h>
#include <WinInet.h>

using namespace WebCore;

namespace WebKit {

class WebFramePrivate::WebFrameData {
public:
    WebFrameData() { }
    ~WebFrameData() { }

    RefPtr<Frame> frame;
    RefPtr<FrameView> frameView;
    WebView* webView;
    WebHost* m_host;
};

WebFramePrivate::WebFramePrivate(char* name, WebView* view, WebHost* host)
: d(new WebFramePrivate::WebFrameData)
{
    d->m_host = host;
    d->webView = view;
    Page* page = new Page();
    Frame* frame = new FrameWin(page, 0, this);
    d->frame = frame;
    frame->deref(); // Frames are created with a refcount of 1.  Release this ref, since we've assigned it to a RefPtr
    page->setMainFrame(frame);
    FrameView* frameView = new FrameView(frame);
    d->frameView = frameView;
    frameView->deref(); // FrameViews are created with a refcount of 1.  Release this ref, since we've assigned it to a RefPtr
    d->frame->setView(frameView);
    d->frameView->setWindowHandle(view->windowHandle());
}

WebFramePrivate::~WebFramePrivate()
{
    delete d->frame->page();
    delete d;
}

void WebFramePrivate::loadFilePath(char* path)
{
    char URL[2048];
    strcpy(URL, "file://localhost/");
    strncat(URL, path, 2020);

    d->frame->didOpenURL(URL);
    d->frame->begin(URL);
    HANDLE fileHandle = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    bool result = false;
    DWORD bytesRead = 0;

    do {
      const int bufferSize = 8193;
      char buffer[bufferSize];
      result = ReadFile(fileHandle, &buffer, bufferSize - 1, &bytesRead, NULL);
      buffer[bytesRead] = '\0';
      d->frame->write(buffer);
      // Check for end of file.
    } while (result && bytesRead);

    CloseHandle(fileHandle);

    d->frame->end();
}

void WebFramePrivate::loadHTMLString(char *html, char *baseURL)
{
    d->frame->begin();
    d->frame->write(html);
    d->frame->end();
}

void WebFramePrivate::openURL(const DeprecatedString& str)
{
    loadURL(str.ascii());
}

void WebFramePrivate::submitForm(const String& method, const KURL& url, const FormData* submitFormData)
{
    // FIXME: This is a dumb implementation, doesn't handle subframes, etc.
    d->frame->didOpenURL(url);
    d->frame->begin(url);
    TransferJob* job;
    if (method == "GET" || !submitFormData)
        job = new TransferJob(this, method, url);
    else
        job = new TransferJob(this, method, url, *submitFormData);
    job->start(d->frame->document()->docLoader());
    if (d->m_host) {
        DeprecatedCString urlString = url.prettyURL().utf8();
        d->m_host->updateLocationBar(urlString);
    }
}

void WebFramePrivate::loadURL(const char* URL)
{
    d->frame->didOpenURL(URL);
    d->frame->begin(URL);
    WebCore::TransferJob* job = new TransferJob(this, "GET", URL);
    job->start(d->frame->document()->docLoader());
    if (d->m_host)
        d->m_host->updateLocationBar(URL);
}

void WebFramePrivate::getURL(char* url, int length)
{
    if (length <= 0)
        return;
    *url = 0;

    DeprecatedCString urlString = d->frame->url().prettyURL().utf8();
    const char* srcURL = urlString;
    if (srcURL) {
        int srcURLLength = strlen(srcURL);
        if (length > srcURLLength)
            strcpy(url, srcURL);
    }
}

void WebFramePrivate::reload()
{
    if (!d->frame->url().url().startsWith("javascript:", false))
        d->frame->scheduleLocationChange(d->frame->url().url(), d->frame->referrer(), true/*lock history*/, true/*userGesture*/);
}

void WebFramePrivate::receivedData(WebCore::TransferJob*, const char* data, int length)
{
    d->frame->write(data, length);
}

void WebFramePrivate::receivedAllData(WebCore::TransferJob* job, WebCore::PlatformData)
{
    d->frame->end();
}

void WebFramePrivate::paint()
{
    d->frameView->layout();

    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(d->webView->windowHandle(), &ps);
    cairo_surface_t* finalSurface = cairo_win32_surface_create(hdc);
    cairo_surface_t* surface = cairo_surface_create_similar(finalSurface,
                                                            CAIRO_CONTENT_COLOR_ALPHA,
                                                            ps.rcPaint.right, ps.rcPaint.bottom);

    cairo_t* context = cairo_create(surface);
    GraphicsContext gc(context);

    IntRect documentDirtyRect = ps.rcPaint;
    documentDirtyRect.move(d->frameView->contentsX(), d->frameView->contentsY());

    // FIXME: We have to set the transform using both cairo and GDI until we use cairo for text.
    HDC surfaceDC = cairo_win32_surface_get_dc(surface);
    SaveDC(surfaceDC);
    OffsetViewportOrgEx(surfaceDC, -d->frameView->contentsX(), -d->frameView->contentsY(), 0);
    cairo_translate(context, -d->frameView->contentsX(), -d->frameView->contentsY());
    d->frame->paint(&gc, documentDirtyRect);
    RestoreDC(surfaceDC, -1);

    cairo_destroy(context);
    context = cairo_create(finalSurface);
    cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
    cairo_set_source_surface(context, surface, 0, 0);
    cairo_rectangle(context, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom);
    cairo_fill(context);
    cairo_destroy(context);

    cairo_surface_destroy(surface);
    cairo_surface_destroy(finalSurface);

    EndPaint(d->webView->windowHandle(), &ps);
}

WebCore::Frame* WebFramePrivate::impl()
{
    return d->frame.get();
}

WebFramePrivate* WebFramePrivate::toPrivate()
{
    return this;
}

}

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "Problem2.h"

/*
https://projecteuler.net/problem=2
Even Fibonacci numbers
Problem 2
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
*/

int Problem2::FibonacciSumEven(int range)
{
    auto sum = 0;

    if (range >= 2)
    {
        sum += 2;
    }

    if (range == 8)
    {
        sum += 8;
    }

    return sum;
}

int Problem2::Fibonacci(int range)
{
    auto value1 = 1;
    auto value2 = 2;

    if (value1 == range || value2 == range)
    {
        return range;
    }

    return value1 + value2;
}<commit_msg>green-commit - Fibonacci_Input4_Returns5<commit_after>#include "stdafx.h"
#include "Problem2.h"

/*
https://projecteuler.net/problem=2
Even Fibonacci numbers
Problem 2
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
*/

int Problem2::FibonacciSumEven(int range)
{
    auto sum = 0;

    if (range >= 2)
    {
        sum += 2;
    }

    if (range == 8)
    {
        sum += 8;
    }

    return sum;
}

int Problem2::Fibonacci(int range)
{
    auto value1 = 1;
    auto value2 = 2;

    if (value1 == range || value2 == range)
    {
        return range;
    }
    else
    {
        auto result = 0;

        for (size_t i = 2; i < range; i++)
        {
            result = value1 + value2;
            value1 = value2;
            value2 = result;
        }

        return result;
    }
}<|endoftext|>


<commit_before>/*
 * TICKS algorithms
 * Author: Frederic Devernay
 * The goal of this algorithm is to compute the position of ticks on an axis.
 * the ticks are positioned at multiples of 1 and 5 of powers of 10
 */
#include "ticks.h"
#include <cmath>
#include <cassert>
// tick_size_10
//
// for a range xmin,xmax drawn with a size range_units (in pixels, or cm...),
// find the smallest tick size, which is a multiple of a power of ten,
// and is drawn larger than min_tick_size_units (in pixels, or cm...).
double
ticks_size_10(double xmin,
              double xmax,
              double range_units,
              double min_tick_size_units)
{
    // first, compute the size of min_tick_size_units
    double min_tick_size = min_tick_size_units * (xmax - xmin) / range_units;
    int next_p10 = std::ceil( std::log10(min_tick_size) );
    double tick_size = std::pow(10.,next_p10);

    assert(tick_size / 10 < min_tick_size);
    assert(tick_size >= min_tick_size);

    return tick_size;
}

// tick_size
//
// for a range xmin,xmax drawn with a size range_units (in pixels, or cm...),
// find the smallest tick size, which is a multiple of a power of ten or of five times a
// power of ten, and is drawn larger than min_tick_size_units (in pixels, or cm...).
void
ticks_size(double xmin,
           double xmax,
           double range_units,
           double min_tick_size_units,
           double *t_size,
           bool* half_tick)
{
    // first, compute the size of min_tick_size_units
    double min_tick_size = min_tick_size_units * (xmax - xmin) / range_units;
    int next_p10 = std::ceil( std::log10(min_tick_size) );

    *t_size = std::pow(10.,next_p10);
    assert(*t_size / 10 < min_tick_size);
    assert(*t_size >= min_tick_size);
    if (*t_size / 2 >= min_tick_size) {
        *t_size /= 2;
        if (half_tick) {
            *half_tick = true;
        }
    } else if (half_tick) {
        *half_tick = false;
    }
}

// ticks_bounds
//
// Find the index of the first and last tick of width tick_width within the interval xmin,xmax.
// if tick_max != 0, an offset is computed to avoid overflow on m1 and m2
// (e.g. if xmin=1+1e-10 and xmax = 1+2e-10).
// This offset is computed so that the maximum tick value within the interval is below tick_max.
// The tick value represents the "majorness" of a tick (tick values are 1, 5, 10, 50, etc.).
// tick_max should be a power of 10. A good value for tick_max is 1000. tick_max should be a multiple of 50
void
ticks_bounds(double xmin,
             double xmax,
             double tick_width,
             bool half_tick,
             int tick_max,
             double *offset,
             int* m1,
             int* m2)
{
    *offset = 0.;
    assert(tick_max >= 0);
    if ( (tick_max > 0) && ( (xmin > 0) || (xmax < 0) ) ) {
        const int h = half_tick ? 2 : 1;
        const int mult = h * tick_width * tick_max;
        // make sure offset is outside of the range (xmin,xmax)
        *offset = mult * ( (xmin > 0) ? std::floor(xmin / mult) : std::ceil(xmax / mult) );
    }
    *m1 = std::ceil( (xmin - *offset) / tick_width );
    *m2 = std::floor( (xmax - *offset) / tick_width );
}

// ticks_fill
//
// fill a vector of ticks.
// the first element in the vector corresponds to m1, the last to m2.
// each value stored in the vector contains the tick size at this index, which can be
// 1 (minor tick), 5 (regular tick), 10 (major tick), 50, 100, etc.
//
// If parameter half_tick is true, this means that the minor tick is actually a half tick,
// i.e. five times a power of ten, and the tick sizes are
// 1 (half minor tick), 2 (minor tick), 10 (regular tick), 20, 100, etc.
//
// tick_max is the maximum tick value that may be used, see tick_bounds().
void
ticks_fill(bool half_tick,
           int tick_max,
           int m1,
           int m2,
           std::vector<int>* ticks)
{
    ticks->resize(m2 - m1 + 1);

    // now all ticks can be obtained by dividing tick_largest by 2, then 5, then 2, then 5, etc.
    int tick_size = 1;
    bool multiply_by_two = half_tick;
    while (tick_size <= tick_max) {
        int tick_1 = std::ceil(m1 / (double)tick_size) * tick_size;
        int tick_2 = std::floor(m2 / (double)tick_size) * tick_size;
        for (int tick = tick_1; tick <= tick_2; tick += tick_size) {
            assert( tick - m1 >= 0 && tick - m1 < (int)ticks->size() );
            (*ticks)[tick - m1] = tick_size;
        }
        if (multiply_by_two) {
            tick_size *= 2;
        } else {
            tick_size *= 5;
        }
        multiply_by_two = !multiply_by_two;
    }

    // last, if 0 is within the interval, give it the value tick_max*10
    if ( (m1 <= 0) && (m2 >= 0) ) {
        (*ticks)[-m1] = 10 * tick_max;
    }
}

// compute alpha value for drawing the ticks
double
ticks_alpha(double min,
            double max,
            double val)
{
    assert(val > 0. && min > 0. && max > 0. && max > min);
    const double alpha = sqrt( (val - min) / (max - min) );

    return std::max( 0.,std::min(alpha,1.) );
}

<commit_msg>ticks.cpp: fix bug NaN<commit_after>/*
 * TICKS algorithms
 * Author: Frederic Devernay
 * The goal of this algorithm is to compute the position of ticks on an axis.
 * the ticks are positioned at multiples of 1 and 5 of powers of 10
 */
#include "ticks.h"
#include <cmath>
#include <cassert>
// tick_size_10
//
// for a range xmin,xmax drawn with a size range_units (in pixels, or cm...),
// find the smallest tick size, which is a multiple of a power of ten,
// and is drawn larger than min_tick_size_units (in pixels, or cm...).
double
ticks_size_10(double xmin,
              double xmax,
              double range_units,
              double min_tick_size_units)
{
    // first, compute the size of min_tick_size_units
    double min_tick_size = min_tick_size_units * (xmax - xmin) / range_units;
    int next_p10 = std::ceil( std::log10(min_tick_size) );
    double tick_size = std::pow(10.,next_p10);

    assert(tick_size / 10 < min_tick_size);
    assert(tick_size >= min_tick_size);

    return tick_size;
}

// tick_size
//
// for a range xmin,xmax drawn with a size range_units (in pixels, or cm...),
// find the smallest tick size, which is a multiple of a power of ten or of five times a
// power of ten, and is drawn larger than min_tick_size_units (in pixels, or cm...).
void
ticks_size(double xmin,
           double xmax,
           double range_units,
           double min_tick_size_units,
           double *t_size,
           bool* half_tick)
{
    // first, compute the size of min_tick_size_units
    double min_tick_size = min_tick_size_units * (xmax - xmin) / range_units;
    int next_p10 = std::ceil( std::log10(min_tick_size) );

    *t_size = std::pow(10.,next_p10);
    assert(*t_size / 10 < min_tick_size);
    assert(*t_size >= min_tick_size);
    if (*t_size / 2 >= min_tick_size) {
        *t_size /= 2;
        if (half_tick) {
            *half_tick = true;
        }
    } else if (half_tick) {
        *half_tick = false;
    }
}

// ticks_bounds
//
// Find the index of the first and last tick of width tick_width within the interval xmin,xmax.
// if tick_max != 0, an offset is computed to avoid overflow on m1 and m2
// (e.g. if xmin=1+1e-10 and xmax = 1+2e-10).
// This offset is computed so that the maximum tick value within the interval is below tick_max.
// The tick value represents the "majorness" of a tick (tick values are 1, 5, 10, 50, etc.).
// tick_max should be a power of 10. A good value for tick_max is 1000. tick_max should be a multiple of 50
void
ticks_bounds(double xmin,
             double xmax,
             double tick_width,
             bool half_tick,
             int tick_max,
             double *offset,
             int* m1,
             int* m2)
{
    *offset = 0.;
    assert(tick_max >= 0);
    if ( (tick_max > 0) && ( (xmin > 0) || (xmax < 0) ) ) {
        const int h = half_tick ? 2 : 1;
        const int mult = h * tick_width * tick_max;
        // make sure offset is outside of the range (xmin,xmax)
        if (mult != 0) {
            *offset = mult * ( (xmin > 0) ? std::floor(xmin / mult) : std::ceil(xmax / mult) );
        } else {
            *offset = 0;
        }
    }
    *m1 = std::ceil( (xmin - *offset) / tick_width );
    *m2 = std::floor( (xmax - *offset) / tick_width );
}

// ticks_fill
//
// fill a vector of ticks.
// the first element in the vector corresponds to m1, the last to m2.
// each value stored in the vector contains the tick size at this index, which can be
// 1 (minor tick), 5 (regular tick), 10 (major tick), 50, 100, etc.
//
// If parameter half_tick is true, this means that the minor tick is actually a half tick,
// i.e. five times a power of ten, and the tick sizes are
// 1 (half minor tick), 2 (minor tick), 10 (regular tick), 20, 100, etc.
//
// tick_max is the maximum tick value that may be used, see tick_bounds().
void
ticks_fill(bool half_tick,
           int tick_max,
           int m1,
           int m2,
           std::vector<int>* ticks)
{
    ticks->resize(m2 - m1 + 1);

    // now all ticks can be obtained by dividing tick_largest by 2, then 5, then 2, then 5, etc.
    int tick_size = 1;
    bool multiply_by_two = half_tick;
    while (tick_size <= tick_max) {
        int tick_1 = std::ceil(m1 / (double)tick_size) * tick_size;
        int tick_2 = std::floor(m2 / (double)tick_size) * tick_size;
        for (int tick = tick_1; tick <= tick_2; tick += tick_size) {
            assert( tick - m1 >= 0 && tick - m1 < (int)ticks->size() );
            (*ticks)[tick - m1] = tick_size;
        }
        if (multiply_by_two) {
            tick_size *= 2;
        } else {
            tick_size *= 5;
        }
        multiply_by_two = !multiply_by_two;
    }

    // last, if 0 is within the interval, give it the value tick_max*10
    if ( (m1 <= 0) && (m2 >= 0) ) {
        (*ticks)[-m1] = 10 * tick_max;
    }
}

// compute alpha value for drawing the ticks
double
ticks_alpha(double min,
            double max,
            double val)
{
    assert(val > 0. && min > 0. && max > 0. && max > min);
    const double alpha = sqrt( (val - min) / (max - min) );

    return std::max( 0.,std::min(alpha,1.) );
}

<|endoftext|>