<commit_before>#include "factory.h"
#include "videosourcefactory.h"
#include "except.h"
#include "iobservable.h"
#include "gil.h"
#ifdef USE_OPENCV
#include "opencv_video_source.h"
#include "opencv_video_target.h"
#endif // USE_OPENCV
#ifdef USE_EPIPHANSDK
#include "epiphansdk_video_source.h"
#endif
#ifdef USE_LIBVLC
#include "vlc_video_source.h"
#endif
#ifdef USE_FFMPEG
#include "ffmpeg_video_target.h"
#endif
#include <boost/python.hpp>
#include <boost/python/exception_translator.hpp>

using namespace boost::python;

class IObservableWrapper : public gg::IObservable, public wrapper<gg::IObservable>
{
public:
    void attach(gg::IObserver & observer)
    {
        if (override f = this->get_override("attach"))
            f(boost::ref(observer));
        else
            gg::IObservable::attach(boost::ref(observer));
    }

    void default_attach(gg::IObserver & observer)
    {
        gg::IObservable::attach(boost::ref(observer));
    }

    void detach(gg::IObserver & observer)
    {
        if (override f = this->get_override("detach"))
            f(boost::ref(observer));
        else
            gg::IObservable::detach(boost::ref(observer));
    }

    void default_detach(gg::IObserver & observer)
    {
        gg::IObservable::detach(boost::ref(observer));
    }
};

class IVideoSourceWrapper : public IVideoSource, public wrapper<IVideoSource>
{
public:
    bool get_frame_dimensions(int & width, int & height)
    {
        return this->get_override("get_frame_dimensions")(width, height);
    }

    bool get_frame(gg::VideoFrame & frame)
    {
        return this->get_override("get_frame")(frame);
    }

    double get_frame_rate()
    {
        return this->get_override("get_frame_rate")();
    }

    void set_sub_frame(int x, int y, int width, int height)
    {
        this->get_override("set_sub_frame")(x, y, width, height);
    }

    void get_full_frame()
    {
        this->get_override("get_full_frame")();
    }
};

/* The inheritance should be public, in order to preserve
 * the public accessibility of the update() method. The
 * Boost.Python examples feature struct's rather than
 * classes, and in struct's everything is public by
 * definition.
 */
class IObserverWrapper : public gg::IObserver, public wrapper<gg::IObserver>
{
public:
    IObserverWrapper()
    {
        /* Default constructor that needs to be called within
         * child Python class, e.g. super(Child, self).__init__()
         * This is normally generated by the compiler
         * automatically, but we define it here explicitly so
         * that it can serve as an example for this complex case.
         */
    }

    void update(gg::VideoFrame & frame)
    {
        gg::ScopedPythonGILLock gil_lock;
        this->get_override("update")(boost::ref(frame));
    }
};

class IVideoTargetWrapper : public gg::IVideoTarget, public wrapper<gg::IVideoTarget>
{
public:
    void init(const std::string filepath, const float framerate)
    {
        this->get_override("init")(filepath, framerate);
    }

    void append(const gg::VideoFrame & frame)
    {
        this->get_override("append")(frame);
    }

    void finalise()
    {
        this->get_override("finalise")();
    }
};

void translate_VideoSourceError(gg::VideoSourceError const & e)
{
    std::string msg;
    msg.append("VideoSourceError: ").append(e.what());
    PyErr_SetString(PyExc_RuntimeError, msg.c_str());
}

void translate_DeviceNotFound(gg::DeviceNotFound const & e)
{
    std::string msg;
    msg.append("DeviceNotFound: ").append(e.what());
    PyErr_SetString(PyExc_IOError, msg.c_str());
}

void translate_DeviceOffline(gg::DeviceOffline const & e)
{
    std::string msg;
    msg.append("DeviceOffline: ").append(e.what());
    PyErr_SetString(PyExc_IOError, msg.c_str());
}

void translate_VideoTargetError(gg::VideoTargetError const & e)
{
    std::string msg;
    msg.append("VideoTargetError: ").append(e.what());
    PyErr_SetString(PyExc_RuntimeError, msg.c_str());
}

void translate_ObserverError(gg::ObserverError const & e)
{
    std::string msg;
    msg.append("ObserverError: ").append(e.what());
    PyErr_SetString(PyExc_RuntimeError, msg.c_str());
}

BOOST_PYTHON_MODULE(pygiftgrab)
{
    PyEval_InitThreads();

    register_exception_translator<gg::VideoSourceError>(&translate_VideoSourceError);
    register_exception_translator<gg::DeviceNotFound>(&translate_DeviceNotFound);
    register_exception_translator<gg::DeviceOffline>(&translate_DeviceOffline);
    register_exception_translator<gg::VideoTargetError>(&translate_VideoTargetError);
    register_exception_translator<gg::ObserverError>(&translate_ObserverError);

    enum_<gg::ColourSpace>("ColourSpace")
        .value("BGRA", gg::ColourSpace::BGRA)
        .value("I420", gg::ColourSpace::I420)
    ;

    enum_<gg::Device>("Device")
        .value("DVI2PCIeDuo_SDI", gg::Device::DVI2PCIeDuo_SDI)
        .value("DVI2PCIeDuo_DVI", gg::Device::DVI2PCIeDuo_DVI)
    ;

    enum_<gg::Storage>("Storage")
        .value("File_HEVC", gg::Storage::File_HEVC)
        .value("File_XviD", gg::Storage::File_XviD)
        .value("File_VP9", gg::Storage::File_VP9)
    ;

    class_<gg::VideoFrame>("VideoFrame", init<enum gg::ColourSpace, bool>())
        .def(init<enum gg::ColourSpace, const size_t, const size_t>())
        .def("rows", &gg::VideoFrame::rows)
        .def("cols", &gg::VideoFrame::cols)
    ;

    class_<IObservableWrapper,boost::noncopyable>("IObservable", no_init)
        .def("attach", &IObservableWrapper::attach)
        .def("detach", &IObservableWrapper::detach)
    ;

    class_<IVideoSource, bases<gg::IObservable>, boost::noncopyable>(
                "IVideoSource", no_init)
    ;

#ifdef USE_OPENCV
    class_<VideoSourceOpenCV, bases<IVideoSource>, boost::noncopyable>(
                "VideoSourceOpenCV", init<int>())
        .def(init<char *>())
        .def("get_frame", &VideoSourceOpenCV::get_frame)
        .def("get_frame_dimensions", &VideoSourceOpenCV::get_frame_dimensions)
        .def("get_frame_rate", &VideoSourceOpenCV::get_frame_rate)
        .def("set_sub_frame", &VideoSourceOpenCV::set_sub_frame)
        .def("get_full_frame", &VideoSourceOpenCV::get_full_frame)
        .def("attach", &gg::IObservable::attach, &IObservableWrapper::default_attach)
        .def("detach", &gg::IObservable::detach, &IObservableWrapper::default_detach)
    ;
#endif // USE_OPENCV

#ifdef USE_EPIPHANSDK
    class_<gg::VideoSourceEpiphanSDK, bases<IVideoSource>, boost::noncopyable>(
                "VideoSourceEpiphanSDK", init<const std::string, const V2U_INT32>())
        .def("get_frame", &gg::VideoSourceEpiphanSDK::get_frame)
        .def("get_frame_dimensions", &gg::VideoSourceEpiphanSDK::get_frame_dimensions)
        .def("get_frame_rate", &gg::VideoSourceEpiphanSDK::get_frame_rate)
        .def("set_sub_frame", &gg::VideoSourceEpiphanSDK::set_sub_frame)
        .def("get_full_frame", &gg::VideoSourceEpiphanSDK::get_full_frame)
        .def("attach", &gg::IObservable::attach, &IObservableWrapper::default_attach)
        .def("detach", &gg::IObservable::detach, &IObservableWrapper::default_detach)
    ;
#endif

#ifdef USE_LIBVLC
    class_<gg::VideoSourceVLC, bases<IVideoSource>, boost::noncopyable>(
                "VideoSourceVLC", init<const std::string>())
        .def("get_frame", &gg::VideoSourceVLC::get_frame)
        .def("get_frame_dimensions", &gg::VideoSourceVLC::get_frame_dimensions)
        .def("get_frame_rate", &gg::VideoSourceVLC::get_frame_rate)
        .def("set_sub_frame", &gg::VideoSourceVLC::set_sub_frame)
        .def("get_full_frame", &gg::VideoSourceVLC::get_full_frame)
        .def("attach", &gg::IObservable::attach, &IObservableWrapper::default_attach)
        .def("detach", &gg::IObservable::detach, &IObservableWrapper::default_detach)
    ;
#endif

    class_<IObserverWrapper, boost::noncopyable>("IObserver")
        .def("update", pure_virtual(&gg::IObserver::update))
    ;

    class_<gg::IVideoTarget, bases<gg::IObserver>, boost::noncopyable>(
                "IVideoTarget", no_init)
        .def("update", &gg::IVideoTarget::update)
    ;

#ifdef USE_FFMPEG
    class_<gg::VideoTargetFFmpeg, bases<gg::IVideoTarget>, boost::noncopyable>(
                "VideoTargetFFmpeg", init<std::string>())
        .def("init", &gg::VideoTargetFFmpeg::init)
        .def("append", &gg::VideoTargetFFmpeg::append)
        .def("finalise", &gg::VideoTargetFFmpeg::finalise)
    ;
#endif

#ifdef USE_OPENCV
    class_<gg::VideoTargetOpenCV, bases<gg::IVideoTarget>, boost::noncopyable>(
                "VideoTargetOpenCV", init<std::string>())
        .def("init", &gg::VideoTargetOpenCV::init)
        .def("append", &gg::VideoTargetOpenCV::append)
        .def("finalise", &gg::VideoTargetOpenCV::finalise)
    ;
#endif // USE_OPENCV

    class_<gg::Factory>("Factory", no_init)
        .def("connect", &gg::Factory::connect,
             /* because client should never delete returned
              * object on its own, but should rather call
              * disconnect when done
              */
             return_value_policy<reference_existing_object>())
        .staticmethod("connect")
        .def("disconnect", &gg::Factory::disconnect)
        .staticmethod("disconnect")
        .def("writer", &gg::Factory::writer,
             // because ownership is passed to client
             return_value_policy<manage_new_object>())
        .staticmethod("writer")
    ;

    class_<gg::VideoSourceFactory, boost::noncopyable>("VideoSourceFactory", no_init)
        .def("get_device", &gg::VideoSourceFactory::get_device
             /* Keep returned pointer (0) alive as long as factory (1) alive.
              * Boost.Python documentation says reference_existing_object is
              * dangerous, but apparently only when no additional lifetime
              * management with a call policy is provided (for details, see:
              * http://www.boost.org/doc/libs/1_39_0/libs/python/doc/v2/reference_existing_object.html
              * ).
              */
             , return_value_policy<reference_existing_object, with_custodian_and_ward_postcall<1, 0> >()
        )
        .def("get_instance", &gg::VideoSourceFactory::get_instance
             , return_internal_reference<>()
        )
        .staticmethod("get_instance")
    ;
}
<commit_msg>Issue #121: using reference_existing_object instead of return_internal_reference as recommended by Boost.Python documentation's singleton example<commit_after>#include "factory.h"
#include "videosourcefactory.h"
#include "except.h"
#include "iobservable.h"
#include "gil.h"
#ifdef USE_OPENCV
#include "opencv_video_source.h"
#include "opencv_video_target.h"
#endif // USE_OPENCV
#ifdef USE_EPIPHANSDK
#include "epiphansdk_video_source.h"
#endif
#ifdef USE_LIBVLC
#include "vlc_video_source.h"
#endif
#ifdef USE_FFMPEG
#include "ffmpeg_video_target.h"
#endif
#include <boost/python.hpp>
#include <boost/python/exception_translator.hpp>

using namespace boost::python;

class IObservableWrapper : public gg::IObservable, public wrapper<gg::IObservable>
{
public:
    void attach(gg::IObserver & observer)
    {
        if (override f = this->get_override("attach"))
            f(boost::ref(observer));
        else
            gg::IObservable::attach(boost::ref(observer));
    }

    void default_attach(gg::IObserver & observer)
    {
        gg::IObservable::attach(boost::ref(observer));
    }

    void detach(gg::IObserver & observer)
    {
        if (override f = this->get_override("detach"))
            f(boost::ref(observer));
        else
            gg::IObservable::detach(boost::ref(observer));
    }

    void default_detach(gg::IObserver & observer)
    {
        gg::IObservable::detach(boost::ref(observer));
    }
};

class IVideoSourceWrapper : public IVideoSource, public wrapper<IVideoSource>
{
public:
    bool get_frame_dimensions(int & width, int & height)
    {
        return this->get_override("get_frame_dimensions")(width, height);
    }

    bool get_frame(gg::VideoFrame & frame)
    {
        return this->get_override("get_frame")(frame);
    }

    double get_frame_rate()
    {
        return this->get_override("get_frame_rate")();
    }

    void set_sub_frame(int x, int y, int width, int height)
    {
        this->get_override("set_sub_frame")(x, y, width, height);
    }

    void get_full_frame()
    {
        this->get_override("get_full_frame")();
    }
};

/* The inheritance should be public, in order to preserve
 * the public accessibility of the update() method. The
 * Boost.Python examples feature struct's rather than
 * classes, and in struct's everything is public by
 * definition.
 */
class IObserverWrapper : public gg::IObserver, public wrapper<gg::IObserver>
{
public:
    IObserverWrapper()
    {
        /* Default constructor that needs to be called within
         * child Python class, e.g. super(Child, self).__init__()
         * This is normally generated by the compiler
         * automatically, but we define it here explicitly so
         * that it can serve as an example for this complex case.
         */
    }

    void update(gg::VideoFrame & frame)
    {
        gg::ScopedPythonGILLock gil_lock;
        this->get_override("update")(boost::ref(frame));
    }
};

class IVideoTargetWrapper : public gg::IVideoTarget, public wrapper<gg::IVideoTarget>
{
public:
    void init(const std::string filepath, const float framerate)
    {
        this->get_override("init")(filepath, framerate);
    }

    void append(const gg::VideoFrame & frame)
    {
        this->get_override("append")(frame);
    }

    void finalise()
    {
        this->get_override("finalise")();
    }
};

void translate_VideoSourceError(gg::VideoSourceError const & e)
{
    std::string msg;
    msg.append("VideoSourceError: ").append(e.what());
    PyErr_SetString(PyExc_RuntimeError, msg.c_str());
}

void translate_DeviceNotFound(gg::DeviceNotFound const & e)
{
    std::string msg;
    msg.append("DeviceNotFound: ").append(e.what());
    PyErr_SetString(PyExc_IOError, msg.c_str());
}

void translate_DeviceOffline(gg::DeviceOffline const & e)
{
    std::string msg;
    msg.append("DeviceOffline: ").append(e.what());
    PyErr_SetString(PyExc_IOError, msg.c_str());
}

void translate_VideoTargetError(gg::VideoTargetError const & e)
{
    std::string msg;
    msg.append("VideoTargetError: ").append(e.what());
    PyErr_SetString(PyExc_RuntimeError, msg.c_str());
}

void translate_ObserverError(gg::ObserverError const & e)
{
    std::string msg;
    msg.append("ObserverError: ").append(e.what());
    PyErr_SetString(PyExc_RuntimeError, msg.c_str());
}

BOOST_PYTHON_MODULE(pygiftgrab)
{
    PyEval_InitThreads();

    register_exception_translator<gg::VideoSourceError>(&translate_VideoSourceError);
    register_exception_translator<gg::DeviceNotFound>(&translate_DeviceNotFound);
    register_exception_translator<gg::DeviceOffline>(&translate_DeviceOffline);
    register_exception_translator<gg::VideoTargetError>(&translate_VideoTargetError);
    register_exception_translator<gg::ObserverError>(&translate_ObserverError);

    enum_<gg::ColourSpace>("ColourSpace")
        .value("BGRA", gg::ColourSpace::BGRA)
        .value("I420", gg::ColourSpace::I420)
    ;

    enum_<gg::Device>("Device")
        .value("DVI2PCIeDuo_SDI", gg::Device::DVI2PCIeDuo_SDI)
        .value("DVI2PCIeDuo_DVI", gg::Device::DVI2PCIeDuo_DVI)
    ;

    enum_<gg::Storage>("Storage")
        .value("File_HEVC", gg::Storage::File_HEVC)
        .value("File_XviD", gg::Storage::File_XviD)
        .value("File_VP9", gg::Storage::File_VP9)
    ;

    class_<gg::VideoFrame>("VideoFrame", init<enum gg::ColourSpace, bool>())
        .def(init<enum gg::ColourSpace, const size_t, const size_t>())
        .def("rows", &gg::VideoFrame::rows)
        .def("cols", &gg::VideoFrame::cols)
    ;

    class_<IObservableWrapper,boost::noncopyable>("IObservable", no_init)
        .def("attach", &IObservableWrapper::attach)
        .def("detach", &IObservableWrapper::detach)
    ;

    class_<IVideoSource, bases<gg::IObservable>, boost::noncopyable>(
                "IVideoSource", no_init)
    ;

#ifdef USE_OPENCV
    class_<VideoSourceOpenCV, bases<IVideoSource>, boost::noncopyable>(
                "VideoSourceOpenCV", init<int>())
        .def(init<char *>())
        .def("get_frame", &VideoSourceOpenCV::get_frame)
        .def("get_frame_dimensions", &VideoSourceOpenCV::get_frame_dimensions)
        .def("get_frame_rate", &VideoSourceOpenCV::get_frame_rate)
        .def("set_sub_frame", &VideoSourceOpenCV::set_sub_frame)
        .def("get_full_frame", &VideoSourceOpenCV::get_full_frame)
        .def("attach", &gg::IObservable::attach, &IObservableWrapper::default_attach)
        .def("detach", &gg::IObservable::detach, &IObservableWrapper::default_detach)
    ;
#endif // USE_OPENCV

#ifdef USE_EPIPHANSDK
    class_<gg::VideoSourceEpiphanSDK, bases<IVideoSource>, boost::noncopyable>(
                "VideoSourceEpiphanSDK", init<const std::string, const V2U_INT32>())
        .def("get_frame", &gg::VideoSourceEpiphanSDK::get_frame)
        .def("get_frame_dimensions", &gg::VideoSourceEpiphanSDK::get_frame_dimensions)
        .def("get_frame_rate", &gg::VideoSourceEpiphanSDK::get_frame_rate)
        .def("set_sub_frame", &gg::VideoSourceEpiphanSDK::set_sub_frame)
        .def("get_full_frame", &gg::VideoSourceEpiphanSDK::get_full_frame)
        .def("attach", &gg::IObservable::attach, &IObservableWrapper::default_attach)
        .def("detach", &gg::IObservable::detach, &IObservableWrapper::default_detach)
    ;
#endif

#ifdef USE_LIBVLC
    class_<gg::VideoSourceVLC, bases<IVideoSource>, boost::noncopyable>(
                "VideoSourceVLC", init<const std::string>())
        .def("get_frame", &gg::VideoSourceVLC::get_frame)
        .def("get_frame_dimensions", &gg::VideoSourceVLC::get_frame_dimensions)
        .def("get_frame_rate", &gg::VideoSourceVLC::get_frame_rate)
        .def("set_sub_frame", &gg::VideoSourceVLC::set_sub_frame)
        .def("get_full_frame", &gg::VideoSourceVLC::get_full_frame)
        .def("attach", &gg::IObservable::attach, &IObservableWrapper::default_attach)
        .def("detach", &gg::IObservable::detach, &IObservableWrapper::default_detach)
    ;
#endif

    class_<IObserverWrapper, boost::noncopyable>("IObserver")
        .def("update", pure_virtual(&gg::IObserver::update))
    ;

    class_<gg::IVideoTarget, bases<gg::IObserver>, boost::noncopyable>(
                "IVideoTarget", no_init)
        .def("update", &gg::IVideoTarget::update)
    ;

#ifdef USE_FFMPEG
    class_<gg::VideoTargetFFmpeg, bases<gg::IVideoTarget>, boost::noncopyable>(
                "VideoTargetFFmpeg", init<std::string>())
        .def("init", &gg::VideoTargetFFmpeg::init)
        .def("append", &gg::VideoTargetFFmpeg::append)
        .def("finalise", &gg::VideoTargetFFmpeg::finalise)
    ;
#endif

#ifdef USE_OPENCV
    class_<gg::VideoTargetOpenCV, bases<gg::IVideoTarget>, boost::noncopyable>(
                "VideoTargetOpenCV", init<std::string>())
        .def("init", &gg::VideoTargetOpenCV::init)
        .def("append", &gg::VideoTargetOpenCV::append)
        .def("finalise", &gg::VideoTargetOpenCV::finalise)
    ;
#endif // USE_OPENCV

    class_<gg::Factory>("Factory", no_init)
        .def("connect", &gg::Factory::connect,
             /* because client should never delete returned
              * object on its own, but should rather call
              * disconnect when done
              */
             return_value_policy<reference_existing_object>())
        .staticmethod("connect")
        .def("disconnect", &gg::Factory::disconnect)
        .staticmethod("disconnect")
        .def("writer", &gg::Factory::writer,
             // because ownership is passed to client
             return_value_policy<manage_new_object>())
        .staticmethod("writer")
    ;

    class_<gg::VideoSourceFactory, boost::noncopyable>("VideoSourceFactory", no_init)
        .def("get_device", &gg::VideoSourceFactory::get_device
             /* Keep returned pointer (0) alive as long as factory (1) alive.
              * Boost.Python documentation says reference_existing_object is
              * dangerous, but apparently only when no additional lifetime
              * management with a call policy is provided (for details, see:
              * http://www.boost.org/doc/libs/1_39_0/libs/python/doc/v2/reference_existing_object.html
              * ).
              */
             , return_value_policy<reference_existing_object, with_custodian_and_ward_postcall<1, 0> >()
        )
        .def("get_instance", &gg::VideoSourceFactory::get_instance
             , return_value_policy<reference_existing_object>()
        )
        .staticmethod("get_instance")
    ;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sfntly/table/bitmap/bitmap_glyph_info.h"

namespace sfntly {

BitmapGlyphInfo::BitmapGlyphInfo(int32_t glyph_id,
                                 int32_t block_offset,
                                 int32_t start_offset,
                                 int32_t length,
                                 int32_t format)
    : glyph_id_(glyph_id),
      relative_(true),
      block_offset_(block_offset),
      start_offset_(start_offset),
      length_(length),
      format_(format) {
}

BitmapGlyphInfo::BitmapGlyphInfo(int32_t glyph_id,
                                 int32_t start_offset,
                                 int32_t length,
                                 int32_t format)
    : glyph_id_(glyph_id),
      relative_(false),
      block_offset_(0),
      start_offset_(start_offset),
      length_(length),
      format_(format) {
}

bool BitmapGlyphInfo::operator==(const BitmapGlyphInfo& rhs) const {
  return (format_ == rhs.format_ &&
          glyph_id_ == rhs.glyph_id_ &&
          length_ == rhs.length_ &&
          offset() == rhs.offset());
}

bool BitmapGlyphInfo::operator==(BitmapGlyphInfo* rhs) {
  if (rhs == NULL) {
    return this == NULL;
  }
  return (format_ == rhs->format() &&
          glyph_id_ == rhs->glyph_id() &&
          length_ == rhs->length() &&
          offset() == rhs->offset());
}

bool StartOffsetComparator::operator()(BitmapGlyphInfo* lhs,
                                       BitmapGlyphInfo* rhs) {
  return lhs->start_offset() > rhs->start_offset();
}

}  // namespace sfntly
<commit_msg>Fix compiler warning<commit_after>/*
 * Copyright 2011 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sfntly/table/bitmap/bitmap_glyph_info.h"

namespace sfntly {

BitmapGlyphInfo::BitmapGlyphInfo(int32_t glyph_id,
                                 int32_t block_offset,
                                 int32_t start_offset,
                                 int32_t length,
                                 int32_t format)
    : glyph_id_(glyph_id),
      relative_(true),
      block_offset_(block_offset),
      start_offset_(start_offset),
      length_(length),
      format_(format) {
}

BitmapGlyphInfo::BitmapGlyphInfo(int32_t glyph_id,
                                 int32_t start_offset,
                                 int32_t length,
                                 int32_t format)
    : glyph_id_(glyph_id),
      relative_(false),
      block_offset_(0),
      start_offset_(start_offset),
      length_(length),
      format_(format) {
}

bool BitmapGlyphInfo::operator==(const BitmapGlyphInfo& rhs) const {
  return (format_ == rhs.format_ &&
          glyph_id_ == rhs.glyph_id_ &&
          length_ == rhs.length_ &&
          offset() == rhs.offset());
}

bool BitmapGlyphInfo::operator==(BitmapGlyphInfo* rhs) {
  if (rhs == NULL) {
    return false;  // Well defined C++ code's this is always not null.
  }
  return (format_ == rhs->format() &&
          glyph_id_ == rhs->glyph_id() &&
          length_ == rhs->length() &&
          offset() == rhs->offset());
}

bool StartOffsetComparator::operator()(BitmapGlyphInfo* lhs,
                                       BitmapGlyphInfo* rhs) {
  return lhs->start_offset() > rhs->start_offset();
}

}  // namespace sfntly
<|endoftext|>


<commit_before>/*
 * Require.cpp
 *
 *  Created on: Jun 24, 2015
 *      Author: gatanasov
 */
#include "Require.h"
#include "File.h"
#include "V8GlobalHelpers.h"
#include "NativeScriptAssert.h"
#include "SimpleProfiler.h"
#include "ExceptionUtil.h"
#include "JniLocalRef.h"
#include "ArgConverter.h"
#include "Constants.h"

#include <sstream>

using namespace v8;
using namespace std;

namespace tns
{
	void Require::Init()
	{
		JEnv env;

		RequireClass = env.FindClass("com/tns/Require");
		assert(RequireClass != nullptr);

		GET_MODULE_PATH_METHOD_ID = env.GetStaticMethodID(RequireClass, "getModulePath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
		assert(GET_MODULE_PATH_METHOD_ID != nullptr);
	}
	Local<String> Require::LoadScriptText(const string& path)
	{
		string content = File::ReadText(path);

		auto separatorIndex = path.find_last_of("/");
		string dirName = path.substr(0, separatorIndex);

		// TODO: Use statically allocated buffer for better performance
		string result(MODULE_PART_1);
		result.reserve(content.length() + 1024);
		result += dirName;
		result += MODULE_PART_2;
		result += path;
		result += MODULE_PART_3;
		result += content;
		result += MODULE_PART_4;

		return ConvertToV8String(result);
	}

	void Require::Callback(const v8::FunctionCallbackInfo<v8::Value>& args)
	{
		SET_PROFILER_FRAME();

		auto isolate = Isolate::GetCurrent();
		if (args.Length() != 2)
		{
			isolate->ThrowException(ConvertToV8String("require should be called with two parameters"));
			return;
		}
		if (!args[0]->IsString())
		{
			isolate->ThrowException(ConvertToV8String("require's first parameter should be string"));
			return;
		}
		if (!args[1]->IsString())
		{
			isolate->ThrowException(ConvertToV8String("require's second parameter should be string"));
			return;
		}

		string moduleName = ConvertToString(args[0].As<String>());
		string callingModuleDirName = ConvertToString(args[1].As<String>());

		JEnv env;
		JniLocalRef jsModulename(env.NewStringUTF(moduleName.c_str()));
		JniLocalRef jsCallingModuleDirName(env.NewStringUTF(callingModuleDirName.c_str()));
		JniLocalRef jsModulePath(env.CallStaticObjectMethod(RequireClass, GET_MODULE_PATH_METHOD_ID, (jstring) jsModulename, (jstring) jsCallingModuleDirName));

		// cache the required modules by full path, not name only, since there might be some collisions with relative paths and names
		string modulePath = ArgConverter::jstringToString((jstring) jsModulePath);

		if(modulePath == ""){
			// module not found
			stringstream ss;
			ss << "Module \"" << moduleName << "\" not found";
			string exception = ss.str();
			ExceptionUtil::GetInstance()->ThrowExceptionToJs(exception);
			return;
		}
		if (modulePath == "EXTERNAL_FILE_ERROR")
		{
			// module not found
			stringstream ss;
			ss << "Module \"" << moduleName << "\" is located on the external storage. Modules can be private application files ONLY";
			string exception = ss.str();
			ExceptionUtil::GetInstance()->ThrowExceptionToJs(exception);
			return;
		}

		auto it = loadedModules.find(modulePath);

		Local<Object> moduleObj;
		bool hasError = false;

		if (it == loadedModules.end())
		{
			moduleObj = CompileAndRun(modulePath, hasError);
		}
		else
		{
			moduleObj = Local<Object>::New(isolate, *((*it).second));
		}

		if(!hasError){
			args.GetReturnValue().Set(moduleObj);
		}
	}

	Local<Object> Require::CompileAndRun(const string& path, bool& hasError)
	{
		auto isolate = Isolate::GetCurrent();

		Local<Value> exportObj = Object::New(isolate);
		Persistent<Object>* persistentExportObj = new Persistent<Object>(isolate, exportObj.As<Object>());
		loadedModules.insert(make_pair(path, persistentExportObj));

		TryCatch tc;
		Local<Object> moduleObj;

		auto scriptText = LoadScriptText(path);

		DEBUG_WRITE("Compiling script (module %s)", path.c_str());
		auto v8Path = ConvertToV8String(path);

		auto cacheData = TryLoadScriptCache(path);

		ScriptOrigin origin(v8Path);
		ScriptCompiler::Source source(scriptText, origin, cacheData);
		ScriptCompiler::CompileOptions option = ScriptCompiler::kNoCompileOptions;
		Local<Script> script;

		if(cacheData != nullptr)
		{
			option = ScriptCompiler::kConsumeCodeCache;
			script = ScriptCompiler::Compile(isolate->GetCurrentContext(), &source, option).ToLocalChecked();
		}
		else
		{
			option = ScriptCompiler::kProduceCodeCache;
			script = ScriptCompiler::Compile(isolate->GetCurrentContext(), &source, option).ToLocalChecked();
			SaveScriptCache(source, path);
		}

		DEBUG_WRITE("Compiled script (module %s)", path.c_str());

		if (ExceptionUtil::GetInstance()->HandleTryCatch(tc, "Script " + path + " contains compilation errors!"))
		{
			hasError = true;
		}
		else if (script.IsEmpty())
		{
			//think about more descriptive message -> [script_name] was empty
			DEBUG_WRITE("%s was empty", path.c_str());
		}
		else
		{
			DEBUG_WRITE("Running script (module %s)", path.c_str());

			auto f = script->Run().As<Function>();
			if (ExceptionUtil::GetInstance()->HandleTryCatch(tc, "Error running script " + path))
			{
				hasError = true;
			}
			else
			{
				auto result = f->Call(Object::New(isolate), 1, &exportObj);
				if(ExceptionUtil::GetInstance()->HandleTryCatch(tc, "Error calling module function "))
				{
					hasError = true;
				}
				else
				{
					moduleObj = result.As<Object>();
					if (moduleObj.IsEmpty())
					{
						auto objectTemplate = ObjectTemplate::New();
						moduleObj = objectTemplate->NewInstance();
					}

					DEBUG_WRITE("Script completed (module %s)", path.c_str());

					if (!moduleObj->StrictEquals(exportObj))
					{
						loadedModules.erase(path);
						persistentExportObj->Reset();
						delete persistentExportObj;

						auto persistentModuleObject = new Persistent<Object>(isolate, moduleObj);
						loadedModules.insert(make_pair(path, persistentModuleObject));
					}
				}
			}
		}

		if(hasError)
		{
			loadedModules.erase(path);
			persistentExportObj->Reset();
			delete persistentExportObj;

			// this handles recursive require calls
			tc.ReThrow();
		}
		else
		{
			return moduleObj;
		}
	}

	ScriptCompiler::CachedData* Require::TryLoadScriptCache(const std::string& path)
	{
		if(!Constants::V8_CACHE_COMPILED_CODE)
		{
			return nullptr;
		}

		auto cachePath = path + ".cache";
		if(!File::Exists(cachePath))
		{
			return nullptr;
		}

		auto file = fopen(cachePath.c_str(), "rb" /* read binary */);
		fseek(file, 0, SEEK_END);
		auto size = ftell(file);
		rewind(file);

		uint8_t* data = new uint8_t[size];
		fread(data, sizeof(uint8_t), size, file);

		auto cache = new ScriptCompiler::CachedData(data, size, ScriptCompiler::CachedData::BufferOwned);

		fclose(file);

		return cache;
	}

	void Require::SaveScriptCache(const ScriptCompiler::Source& source, const std::string& path)
	{
		int length = source.GetCachedData()->length;
		auto cachePath = path + ".cache";
		auto file = fopen(cachePath.c_str(), "wb" /* write binary */);
		fwrite(source.GetCachedData()->data, sizeof(uint8_t), length, file);
		fclose(file);
	}

	const char* Require::MODULE_PART_1 = "(function(){\n var module = {}; module.exports = arguments[0]; var exports = module.exports; var __dirname = \"";
	const char* Require::MODULE_PART_2 = "\"; var __filename = \"";
	const char* Require::MODULE_PART_3 = "\"; function require(moduleName){ return __global.require(moduleName, __dirname); } module.filename = __filename; this.__extends = __global.__extends; \n";
	const char* Require::MODULE_PART_4 = "\n return module.exports; \n})";

	map<string, Persistent<Object>*> Require::loadedModules;
	jmethodID Require::GET_MODULE_PATH_METHOD_ID = nullptr;
	jclass Require::RequireClass = nullptr;
}
<commit_msg>Produce code cache only if needed.<commit_after>/*
 * Require.cpp
 *
 *  Created on: Jun 24, 2015
 *      Author: gatanasov
 */
#include "Require.h"
#include "File.h"
#include "V8GlobalHelpers.h"
#include "NativeScriptAssert.h"
#include "SimpleProfiler.h"
#include "ExceptionUtil.h"
#include "JniLocalRef.h"
#include "ArgConverter.h"
#include "Constants.h"

#include <sstream>

using namespace v8;
using namespace std;

namespace tns
{
	void Require::Init()
	{
		JEnv env;

		RequireClass = env.FindClass("com/tns/Require");
		assert(RequireClass != nullptr);

		GET_MODULE_PATH_METHOD_ID = env.GetStaticMethodID(RequireClass, "getModulePath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
		assert(GET_MODULE_PATH_METHOD_ID != nullptr);
	}
	Local<String> Require::LoadScriptText(const string& path)
	{
		string content = File::ReadText(path);

		auto separatorIndex = path.find_last_of("/");
		string dirName = path.substr(0, separatorIndex);

		// TODO: Use statically allocated buffer for better performance
		string result(MODULE_PART_1);
		result.reserve(content.length() + 1024);
		result += dirName;
		result += MODULE_PART_2;
		result += path;
		result += MODULE_PART_3;
		result += content;
		result += MODULE_PART_4;

		return ConvertToV8String(result);
	}

	void Require::Callback(const v8::FunctionCallbackInfo<v8::Value>& args)
	{
		SET_PROFILER_FRAME();

		auto isolate = Isolate::GetCurrent();
		if (args.Length() != 2)
		{
			isolate->ThrowException(ConvertToV8String("require should be called with two parameters"));
			return;
		}
		if (!args[0]->IsString())
		{
			isolate->ThrowException(ConvertToV8String("require's first parameter should be string"));
			return;
		}
		if (!args[1]->IsString())
		{
			isolate->ThrowException(ConvertToV8String("require's second parameter should be string"));
			return;
		}

		string moduleName = ConvertToString(args[0].As<String>());
		string callingModuleDirName = ConvertToString(args[1].As<String>());

		JEnv env;
		JniLocalRef jsModulename(env.NewStringUTF(moduleName.c_str()));
		JniLocalRef jsCallingModuleDirName(env.NewStringUTF(callingModuleDirName.c_str()));
		JniLocalRef jsModulePath(env.CallStaticObjectMethod(RequireClass, GET_MODULE_PATH_METHOD_ID, (jstring) jsModulename, (jstring) jsCallingModuleDirName));

		// cache the required modules by full path, not name only, since there might be some collisions with relative paths and names
		string modulePath = ArgConverter::jstringToString((jstring) jsModulePath);

		if(modulePath == ""){
			// module not found
			stringstream ss;
			ss << "Module \"" << moduleName << "\" not found";
			string exception = ss.str();
			ExceptionUtil::GetInstance()->ThrowExceptionToJs(exception);
			return;
		}
		if (modulePath == "EXTERNAL_FILE_ERROR")
		{
			// module not found
			stringstream ss;
			ss << "Module \"" << moduleName << "\" is located on the external storage. Modules can be private application files ONLY";
			string exception = ss.str();
			ExceptionUtil::GetInstance()->ThrowExceptionToJs(exception);
			return;
		}

		auto it = loadedModules.find(modulePath);

		Local<Object> moduleObj;
		bool hasError = false;

		if (it == loadedModules.end())
		{
			moduleObj = CompileAndRun(modulePath, hasError);
		}
		else
		{
			moduleObj = Local<Object>::New(isolate, *((*it).second));
		}

		if(!hasError){
			args.GetReturnValue().Set(moduleObj);
		}
	}

	Local<Object> Require::CompileAndRun(const string& path, bool& hasError)
	{
		auto isolate = Isolate::GetCurrent();

		Local<Value> exportObj = Object::New(isolate);
		Persistent<Object>* persistentExportObj = new Persistent<Object>(isolate, exportObj.As<Object>());
		loadedModules.insert(make_pair(path, persistentExportObj));

		TryCatch tc;
		Local<Object> moduleObj;

		auto scriptText = LoadScriptText(path);

		DEBUG_WRITE("Compiling script (module %s)", path.c_str());
		auto v8Path = ConvertToV8String(path);

		auto cacheData = TryLoadScriptCache(path);

		ScriptOrigin origin(v8Path);
		ScriptCompiler::Source source(scriptText, origin, cacheData);
		ScriptCompiler::CompileOptions option = ScriptCompiler::kNoCompileOptions;
		Local<Script> script;

		if(cacheData != nullptr)
		{
			option = ScriptCompiler::kConsumeCodeCache;
			script = ScriptCompiler::Compile(isolate->GetCurrentContext(), &source, option).ToLocalChecked();
		}
		else
		{
			if(Constants::V8_CACHE_COMPILED_CODE)
			{
				option = ScriptCompiler::kProduceCodeCache;
			}
			script = ScriptCompiler::Compile(isolate->GetCurrentContext(), &source, option).ToLocalChecked();
			SaveScriptCache(source, path);
		}

		DEBUG_WRITE("Compiled script (module %s)", path.c_str());

		if (ExceptionUtil::GetInstance()->HandleTryCatch(tc, "Script " + path + " contains compilation errors!"))
		{
			hasError = true;
		}
		else if (script.IsEmpty())
		{
			//think about more descriptive message -> [script_name] was empty
			DEBUG_WRITE("%s was empty", path.c_str());
		}
		else
		{
			DEBUG_WRITE("Running script (module %s)", path.c_str());

			auto f = script->Run().As<Function>();
			if (ExceptionUtil::GetInstance()->HandleTryCatch(tc, "Error running script " + path))
			{
				hasError = true;
			}
			else
			{
				auto result = f->Call(Object::New(isolate), 1, &exportObj);
				if(ExceptionUtil::GetInstance()->HandleTryCatch(tc, "Error calling module function "))
				{
					hasError = true;
				}
				else
				{
					moduleObj = result.As<Object>();
					if (moduleObj.IsEmpty())
					{
						auto objectTemplate = ObjectTemplate::New();
						moduleObj = objectTemplate->NewInstance();
					}

					DEBUG_WRITE("Script completed (module %s)", path.c_str());

					if (!moduleObj->StrictEquals(exportObj))
					{
						loadedModules.erase(path);
						persistentExportObj->Reset();
						delete persistentExportObj;

						auto persistentModuleObject = new Persistent<Object>(isolate, moduleObj);
						loadedModules.insert(make_pair(path, persistentModuleObject));
					}
				}
			}
		}

		if(hasError)
		{
			loadedModules.erase(path);
			persistentExportObj->Reset();
			delete persistentExportObj;

			// this handles recursive require calls
			tc.ReThrow();
		}
		else
		{
			return moduleObj;
		}
	}

	ScriptCompiler::CachedData* Require::TryLoadScriptCache(const std::string& path)
	{
		if(!Constants::V8_CACHE_COMPILED_CODE)
		{
			return nullptr;
		}

		auto cachePath = path + ".cache";
		if(!File::Exists(cachePath))
		{
			return nullptr;
		}

		auto file = fopen(cachePath.c_str(), "rb" /* read binary */);
		fseek(file, 0, SEEK_END);
		auto size = ftell(file);
		rewind(file);

		uint8_t* data = new uint8_t[size];
		fread(data, sizeof(uint8_t), size, file);

		auto cache = new ScriptCompiler::CachedData(data, size, ScriptCompiler::CachedData::BufferOwned);

		fclose(file);

		return cache;
	}

	void Require::SaveScriptCache(const ScriptCompiler::Source& source, const std::string& path)
	{
		int length = source.GetCachedData()->length;
		auto cachePath = path + ".cache";
		auto file = fopen(cachePath.c_str(), "wb" /* write binary */);
		fwrite(source.GetCachedData()->data, sizeof(uint8_t), length, file);
		fclose(file);
	}

	const char* Require::MODULE_PART_1 = "(function(){\n var module = {}; module.exports = arguments[0]; var exports = module.exports; var __dirname = \"";
	const char* Require::MODULE_PART_2 = "\"; var __filename = \"";
	const char* Require::MODULE_PART_3 = "\"; function require(moduleName){ return __global.require(moduleName, __dirname); } module.filename = __filename; this.__extends = __global.__extends; \n";
	const char* Require::MODULE_PART_4 = "\n return module.exports; \n})";

	map<string, Persistent<Object>*> Require::loadedModules;
	jmethodID Require::GET_MODULE_PATH_METHOD_ID = nullptr;
	jclass Require::RequireClass = nullptr;
}
<|endoftext|>


<commit_before>#include "Interface/UserInterface.h"
#include "Interface/SimRobotInterface.h"
#include "Main/SimViewProgram.h"
#include <utils/StatCollector.h>
#include <GL/glui.h>
#include <fstream>
using namespace Math3D;
using namespace GLDraw;

enum {
  SIMULATE_BUTTON_ID,
  RESET_BUTTON_ID,
  UI_LISTBOX_ID
};

//planner update time step
double dt=0.01;
//coefficient for the path duration cost in RealTimePlannerBase
double timeCostCoeff = 0.0;

class UserTrialProgram : public SimViewProgram
{
public:
  RobotWorld planningWorld;
  WorldPlannerSettings settings;
  string initialState;

  string logFile;
  SmartPointer<SimRobotInterface> robotInterface;
  vector<SmartPointer<RobotUserInterface> > uis;
  int currentUI,oldUI;

  //GUI state
  GLUI* glui;
  GLUI_Listbox* ui_listbox;

  int drawDesired,drawPath,drawUI,drawContacts;

  UserTrialProgram(RobotWorld* world)
    :SimViewProgram(world)
  {
    settings.InitializeDefault(*world);
    logFile = "trial.log";
  }

  void LogBegin(string parameters="")
  {
    ofstream out(logFile.c_str(),ios::out | ios::app);
    out<<"Begin "<<parameters<<endl;
    out.close();
  }

  void LogActivate(string result)
  {
    ofstream out(logFile.c_str(),ios::out | ios::app);
    out<<"Activate "<<uis[currentUI]->Name()<<" "<<sim.time<<" "<<result<<endl;
    out.close();
  }

  void LogDeactivate(string result)
  {
    ofstream out(logFile.c_str(),ios::out | ios::app);
    out<<"Deactivate "<<uis[currentUI]->Name()<<" "<<sim.time<<" "<<result<<endl;
    out.close();
  }

  void LogUpdate(string result)
  {
    if(!result.empty()) {
      ofstream out(logFile.c_str(),ios::out | ios::app);
      out<<"Update "<<uis[currentUI]->Name()<<" "<<sim.time<<" "<<result<<endl;
      out.close();
    }
  }

  void LogMouseInput(string result)
  {
    if(!result.empty()) {
      ofstream out(logFile.c_str(),ios::out | ios::app);
      out<<"MouseInput "<<uis[currentUI]->Name()<<" "<<sim.time<<" "<<result<<endl;
      out.close();
    }
  }

  void LogKeypress(string result)
  {
    if(!result.empty()) {
      ofstream out(logFile.c_str(),ios::out | ios::app);
      out<<"Keypress "<<uis[currentUI]->Name()<<" "<<sim.time<<" "<<result<<endl;
      out.close();
    }
  }

  virtual bool Initialize()
  {
    drawDesired = 1;
    drawPath = 0;
    drawUI = 1;
    drawContacts = 1;

    robotInterface = new SimRobotInterface(&sim);
    CopyWorld(*world,planningWorld);

    uis.resize(0);
    uis.push_back(new JointCommandInterface);
    uis.push_back(new IKCommandInterface);
    uis.push_back(new IKPlannerCommandInterface);
    uis.push_back(new RRTCommandInterface);
#ifndef WIN32
    uis.push_back(new MTIKPlannerCommandInterface);
    uis.push_back(new MTRRTCommandInterface);
#endif //WIN32
    for(size_t i=0;i<uis.size();i++) {
      uis[i]->world = world;
      uis[i]->robotInterface = robotInterface;
      uis[i]->planningWorld = &planningWorld;
      uis[i]->viewport = &viewport;
      uis[i]->settings = &settings;
    }
    currentUI = oldUI = 0;

    //activate current UI
    string res=uis[currentUI]->ActivateEvent(true);
    LogActivate(res);

    if(!WorldViewProgram::Initialize()) return false;

    glui = GLUI_Master.create_glui_subwindow(main_window,GLUI_SUBWINDOW_RIGHT);
    glui->set_main_gfx_window(main_window);
    glui->add_button("Simulate",SIMULATE_BUTTON_ID,ControlFunc);
    glui->add_button("Reset",RESET_BUTTON_ID,ControlFunc);
    ui_listbox = glui->add_listbox("UI",&currentUI,UI_LISTBOX_ID,ControlFunc);
    for(size_t i=0;i<uis.size();i++) {
      char buf[256];
      strcpy(buf,uis[i]->Description().c_str());
      ui_listbox->add_item(i,buf);
    }

    glui->add_checkbox("Draw desired",&drawDesired);
    glui->add_checkbox("Draw UI",&drawUI);
    glui->add_checkbox("Draw path",&drawPath);
    glui->add_checkbox("Draw contacts",&drawContacts);

    printf("Done initializing...\n");
    return true;
  }

  virtual void RenderWorld()
  {
    Robot* robot=world->robots[0].robot;
    RobotController* rc=sim.robotControllers[0];

    SimViewProgram::RenderWorld();

    //draw current commanded configuration -- transparent
    GLColor newColor(0,1,0,0.5);
    world->robots[0].view.SetColors(newColor);
    Config q;
    sim.controlSimulators[0].GetCommandedConfig(q);
    robot->UpdateConfig(q);
    world->robots[0].view.Draw();

    if(drawDesired) {
      Config curBest;
      robotInterface->GetEndConfig(curBest);
      robot->UpdateConfig(curBest);
      world->robots[0].view.SetColors(GLColor(1,1,0,0.5));
      world->robots[0].view.Draw();
      /*
      if(curGoal) {
	glPointSize(5.0);
	glDisable(GL_LIGHTING);
	glColor3f(1,1,0);
	glBegin(GL_POINTS);
	glVertex3v(curGoal->ikGoal.endPosition);
	glEnd();

	//draw end effector path
	glColor3f(1,0.5,0);
	glBegin(GL_LINE_STRIP);
	for(Real t=c->pathParameter;t<c->ramp.endTime;t+=0.05) {
	  c->ramp.Evaluate(t,robot->q);
	  robot->UpdateFrames();
	  glVertex3v(robot->links[curGoal->ikGoal.link].T_World*curGoal->ikGoal.localPosition);
	}
	for(size_t i=0;i<c->path.ramps.size();i++) {
	  for(Real t=0;t<c->path.ramps[i].endTime;t+=0.05) {
	    c->path.ramps[i].Evaluate(t,robot->q);
	    robot->UpdateFrames();
	    glVertex3v(robot->links[curGoal->ikGoal.link].T_World*curGoal->ikGoal.localPosition);
	  }
	}
	glEnd();
	glEnable(GL_LIGHTING);
      }
      */
    }
    if(drawUI) {
      uis[currentUI]->DrawGL();
    }

    //draw desired path
    if(drawPath) {
      RobotController* rc=sim.robotControllers[0];
      for(size_t i=0;i<robot->drivers.size();i++) {
	robot->SetDriverValue(i,rc->command->actuators[i].qdes);
      }
      robot->UpdateFrames();
      world->robots[0].view.SetColors(GLColor(0,1,0,0.5));
      world->robots[0].view.Draw();
    }

    //draw collision feedback
    if(drawContacts) {
      DrawContacts();
    }
  }

  virtual void RenderScreen()
  {
    void* fontface = GLUT_BITMAP_TIMES_ROMAN_24;
    const int fontheight = 24;
    const int lineSpacing = 36;
    const int margin = 5;
    int x,y;

    glDisable(GL_LIGHTING);
    glDisable(GL_DEPTH_TEST);

    x = 20;
    y = 40;

    if(!simulate) {
      glColor3f(1,1,0);
      glRasterPos2i(x,y);
      glutBitmapString(fontface,"Select a desired UI mode");
      y += lineSpacing;
      glRasterPos2i(x,y);
      glutBitmapString(fontface,"Press Simulate when you are ready");
    }
    else {
      glColor3f(1,1,1);
      glRasterPos2i(x,y);
      glutBitmapString(fontface,uis[currentUI]->Instructions().c_str());
      y += lineSpacing;
    }

    glEnable(GL_DEPTH_TEST);
  }

  virtual void Handle_Control(int id)
  {
    switch(id) {
    case SIMULATE_BUTTON_ID:
      if(simulate) {
	simulate=0;
	SleepIdleCallback();
      }
      else {
	simulate=1;
	SleepIdleCallback(0);
      }
      break;
    case RESET_BUTTON_ID:
      simulate = 0;
      ResetSim();
      break;
    case UI_LISTBOX_ID:
      {
	string res=uis[oldUI]->ActivateEvent(false);
	LogDeactivate(res);
	res=uis[currentUI]->ActivateEvent(true);
	LogActivate(res);
	oldUI=currentUI;
      }
      break;
    }
  }

  void BeginDrag(int x,int y,int button,int modifiers)
  {
    if(button == GLUT_RIGHT_BUTTON) {
    }
    else {
      WorldViewProgram::BeginDrag(x,y,button,modifiers);
    }
  }

  void EndDrag(int x,int y,int button,int modifiers)
  {
    if(button == GLUT_RIGHT_BUTTON) {
      string res=uis[currentUI]->MouseInputEvent(0,0,true);
      LogMouseInput(res);
    }
  }

  virtual void DoFreeDrag(int dx,int dy,int button)
  {
    if(button == GLUT_LEFT_BUTTON)  DragRotate(dx,dy);
    else if(button == GLUT_RIGHT_BUTTON) {
      string res=uis[currentUI]->MouseInputEvent(dx,dy,true);
      LogMouseInput(res);
    }
  }

  virtual void DoCtrlDrag(int dx,int dy,int button)
  {
    if(button == GLUT_LEFT_BUTTON)  DragPan(dx,dy);
  }

  virtual void DoAltDrag(int dx,int dy,int button)
  {
    if(button == GLUT_LEFT_BUTTON)  DragZoom(dx,dy);
  }

  virtual void DoShiftDrag(int dx,int dy,int button)
  {
    if(button == GLUT_LEFT_BUTTON) { camera.dist *= (1 + 0.01*Real(dy)); }
  }

  virtual void Handle_Motion(int x,int y)
  {
    string res=uis[currentUI]->MouseInputEvent(x,y,false);
    LogMouseInput(res);
    Refresh();
  }

  virtual void Handle_Keypress(unsigned char key,int x,int y)
  {
    string res=uis[currentUI]->KeypressEvent(key,x,y);
    LogKeypress(res);
    Refresh();
  }

  virtual void Handle_Idle() {
    if(simulate) {
      Timer timer;
      string res=uis[currentUI]->UpdateEvent();
      LogUpdate(res);

      sim.Advance(dt);
      Refresh();

      SleepIdleCallback(int(Max(0.0,dt-timer.ElapsedTime())*1000.0));
    }
    WorldViewProgram::Handle_Idle();
  }
};

int main(int argc, char** argv)
{
  if(argc < 2) {
    printf("USAGE: UserTrials XML_file [log file]\n");
    return 0;
  }
  RobotWorld world;
  world.lights.resize(1);
  world.lights[0].setColor(GLColor(1,1,1));
  world.lights[0].setDirectionalLight(Vector3(0.2,-0.4,1));
  world.lights[0].setColor(GLColor(1,1,1));

  XmlWorld xmlWorld;
  char* logFile = NULL;
  for(int i=1;i<argc;i++) {
    const char* ext=FileExtension(argv[i]);
    if(0==strcmp(ext,"rob")) {
      if(world.LoadRobot(argv[i])<0) {
	printf("Error loading robot file %s\n",argv[i]);
	return 1;
      }
    }
    else if(0==strcmp(ext,"env") || 0==strcmp(ext,"tri")) {
      if(world.LoadTerrain(argv[i])<0) {
	printf("Error loading terrain file %s\n",argv[i]);
	return 1;
      }
    }
    else if(0==strcmp(ext,"obj")) {
      if(world.LoadRigidObject(argv[i])<0) {
	printf("Error loading rigid object file %s\n",argv[i]);
	return 1;
      }
    }
    else if(0==strcmp(ext,"xml")) {
      if(!xmlWorld.Load(argv[i])) {
	printf("Error loading world file %s\n",argv[i]);
	return 1;
      }
      if(!xmlWorld.GetWorld(world)) {
	printf("Error loading world from %s\n",argv[i]);
	return 1;
      }
    }
    else if(0==strcmp(ext,"log")) {
      logFile = argv[i];
    }
    else {
      printf("Unknown file extension %s on file %s\n",ext,argv[i]);
      return 1;
    }
  }

  UserTrialProgram program(&world);
  if(logFile) program.logFile = logFile;
  program.InitSim();

  stringstream params;
  for(int i=1;i<argc;i++)
    params<<argv[i]<<" ";
  program.LogBegin(params.str());
  return program.Run();
}
<commit_msg>Now drawing the planned path works<commit_after>#include "Interface/UserInterface.h"
#include "Interface/SimRobotInterface.h"
#include "Main/SimViewProgram.h"
#include <utils/StatCollector.h>
#include <GL/glui.h>
#include <fstream>
using namespace Math3D;
using namespace GLDraw;

enum {
  SIMULATE_BUTTON_ID,
  RESET_BUTTON_ID,
  UI_LISTBOX_ID
};

//planner update time step
double dt=0.01;
//coefficient for the path duration cost in RealTimePlannerBase
double timeCostCoeff = 0.0;

class UserTrialProgram : public SimViewProgram
{
public:
  RobotWorld planningWorld;
  WorldPlannerSettings settings;
  string initialState;

  string logFile;
  SmartPointer<SimRobotInterface> robotInterface;
  vector<SmartPointer<RobotUserInterface> > uis;
  int currentUI,oldUI;

  //GUI state
  GLUI* glui;
  GLUI_Listbox* ui_listbox;

  int drawDesired,drawPath,drawUI,drawContacts;

  UserTrialProgram(RobotWorld* world)
    :SimViewProgram(world)
  {
    settings.InitializeDefault(*world);
    logFile = "trial.log";
  }

  void LogBegin(string parameters="")
  {
    ofstream out(logFile.c_str(),ios::out | ios::app);
    out<<"Begin "<<parameters<<endl;
    out.close();
  }

  void LogActivate(string result)
  {
    ofstream out(logFile.c_str(),ios::out | ios::app);
    out<<"Activate "<<uis[currentUI]->Name()<<" "<<sim.time<<" "<<result<<endl;
    out.close();
  }

  void LogDeactivate(string result)
  {
    ofstream out(logFile.c_str(),ios::out | ios::app);
    out<<"Deactivate "<<uis[currentUI]->Name()<<" "<<sim.time<<" "<<result<<endl;
    out.close();
  }

  void LogUpdate(string result)
  {
    if(!result.empty()) {
      ofstream out(logFile.c_str(),ios::out | ios::app);
      out<<"Update "<<uis[currentUI]->Name()<<" "<<sim.time<<" "<<result<<endl;
      out.close();
    }
  }

  void LogMouseInput(string result)
  {
    if(!result.empty()) {
      ofstream out(logFile.c_str(),ios::out | ios::app);
      out<<"MouseInput "<<uis[currentUI]->Name()<<" "<<sim.time<<" "<<result<<endl;
      out.close();
    }
  }

  void LogKeypress(string result)
  {
    if(!result.empty()) {
      ofstream out(logFile.c_str(),ios::out | ios::app);
      out<<"Keypress "<<uis[currentUI]->Name()<<" "<<sim.time<<" "<<result<<endl;
      out.close();
    }
  }

  virtual bool Initialize()
  {
    drawDesired = 1;
    drawPath = 0;
    drawUI = 1;
    drawContacts = 1;

    robotInterface = new SimRobotInterface(&sim);
    CopyWorld(*world,planningWorld);

    uis.resize(0);
    uis.push_back(new JointCommandInterface);
    uis.push_back(new IKCommandInterface);
    uis.push_back(new IKPlannerCommandInterface);
    uis.push_back(new RRTCommandInterface);
#ifndef WIN32
    uis.push_back(new MTIKPlannerCommandInterface);
    uis.push_back(new MTRRTCommandInterface);
#endif //WIN32
    for(size_t i=0;i<uis.size();i++) {
      uis[i]->world = world;
      uis[i]->robotInterface = robotInterface;
      uis[i]->planningWorld = &planningWorld;
      uis[i]->viewport = &viewport;
      uis[i]->settings = &settings;
    }
    currentUI = oldUI = 0;

    //activate current UI
    string res=uis[currentUI]->ActivateEvent(true);
    LogActivate(res);

    if(!WorldViewProgram::Initialize()) return false;

    glui = GLUI_Master.create_glui_subwindow(main_window,GLUI_SUBWINDOW_RIGHT);
    glui->set_main_gfx_window(main_window);
    glui->add_button("Simulate",SIMULATE_BUTTON_ID,ControlFunc);
    glui->add_button("Reset",RESET_BUTTON_ID,ControlFunc);
    ui_listbox = glui->add_listbox("UI",&currentUI,UI_LISTBOX_ID,ControlFunc);
    for(size_t i=0;i<uis.size();i++) {
      char buf[256];
      strcpy(buf,uis[i]->Description().c_str());
      ui_listbox->add_item(i,buf);
    }

    glui->add_checkbox("Draw desired",&drawDesired);
    glui->add_checkbox("Draw UI",&drawUI);
    glui->add_checkbox("Draw path",&drawPath);
    glui->add_checkbox("Draw contacts",&drawContacts);

    printf("Done initializing...\n");
    return true;
  }

  virtual void RenderWorld()
  {
    Robot* robot=world->robots[0].robot;
    RobotController* rc=sim.robotControllers[0];

    SimViewProgram::RenderWorld();

    //draw current commanded configuration -- transparent
    GLColor newColor(0,1,0,0.5);
    world->robots[0].view.SetColors(newColor);
    Config q;
    sim.controlSimulators[0].GetCommandedConfig(q);
    robot->UpdateConfig(q);
    world->robots[0].view.Draw();

    if(drawDesired) {
      Config curBest;
      robotInterface->GetEndConfig(curBest);
      robot->UpdateConfig(curBest);
      world->robots[0].view.SetColors(GLColor(1,1,0,0.5));
      world->robots[0].view.Draw();
      /*
      if(curGoal) {
	glPointSize(5.0);
	glDisable(GL_LIGHTING);
	glColor3f(1,1,0);
	glBegin(GL_POINTS);
	glVertex3v(curGoal->ikGoal.endPosition);
	glEnd();

	//draw end effector path
	glColor3f(1,0.5,0);
	glBegin(GL_LINE_STRIP);
	for(Real t=c->pathParameter;t<c->ramp.endTime;t+=0.05) {
	  c->ramp.Evaluate(t,robot->q);
	  robot->UpdateFrames();
	  glVertex3v(robot->links[curGoal->ikGoal.link].T_World*curGoal->ikGoal.localPosition);
	}
	for(size_t i=0;i<c->path.ramps.size();i++) {
	  for(Real t=0;t<c->path.ramps[i].endTime;t+=0.05) {
	    c->path.ramps[i].Evaluate(t,robot->q);
	    robot->UpdateFrames();
	    glVertex3v(robot->links[curGoal->ikGoal.link].T_World*curGoal->ikGoal.localPosition);
	  }
	}
	glEnd();
	glEnable(GL_LIGHTING);
      }
      */
    }
    if(drawUI) {
      uis[currentUI]->DrawGL();
    }

    //draw desired path
    if(drawPath) {
      Real tstart = robotInterface->GetCurTime();
      Real tend = robotInterface->GetEndTime();
      Real dt = 0.05;
      //draw end effector path
      glDisable(GL_LIGHTING);
      glColor3f(1,1,0);
      glLineWidth(2.0);
      glBegin(GL_LINES);
      int istart=(int)Ceil(tstart/dt);
      int iend=(int)Ceil(tend/dt);
      for(int i=istart;i<iend;i++) {
	Real t1=i*dt;
	Real t2=t1+0.5*dt;
	robotInterface->GetConfig(t1,robot->q);
	robot->UpdateFrames();
	glVertex3v(robot->links.back().T_World.t);
	robotInterface->GetConfig(t2,robot->q);
	robot->UpdateFrames();
	glVertex3v(robot->links.back().T_World.t);
      }
      glEnd();
    }

    //draw collision feedback
    if(drawContacts) {
      DrawContacts();
    }
  }

  virtual void RenderScreen()
  {
    void* fontface = GLUT_BITMAP_TIMES_ROMAN_24;
    const int fontheight = 24;
    const int lineSpacing = 36;
    const int margin = 5;
    int x,y;

    glDisable(GL_LIGHTING);
    glDisable(GL_DEPTH_TEST);

    x = 20;
    y = 40;

    if(!simulate) {
      glColor3f(1,1,0);
      glRasterPos2i(x,y);
      glutBitmapString(fontface,"Select a desired UI mode");
      y += lineSpacing;
      glRasterPos2i(x,y);
      glutBitmapString(fontface,"Press Simulate when you are ready");
    }
    else {
      glColor3f(1,1,1);
      glRasterPos2i(x,y);
      glutBitmapString(fontface,uis[currentUI]->Instructions().c_str());
      y += lineSpacing;
    }

    glEnable(GL_DEPTH_TEST);
  }

  virtual void Handle_Control(int id)
  {
    switch(id) {
    case SIMULATE_BUTTON_ID:
      if(simulate) {
	simulate=0;
	SleepIdleCallback();
      }
      else {
	simulate=1;
	SleepIdleCallback(0);
      }
      break;
    case RESET_BUTTON_ID:
      simulate = 0;
      ResetSim();
      break;
    case UI_LISTBOX_ID:
      {
	string res=uis[oldUI]->ActivateEvent(false);
	LogDeactivate(res);
	res=uis[currentUI]->ActivateEvent(true);
	LogActivate(res);
	oldUI=currentUI;
      }
      break;
    }
  }

  void BeginDrag(int x,int y,int button,int modifiers)
  {
    if(button == GLUT_RIGHT_BUTTON) {
    }
    else {
      WorldViewProgram::BeginDrag(x,y,button,modifiers);
    }
  }

  void EndDrag(int x,int y,int button,int modifiers)
  {
    if(button == GLUT_RIGHT_BUTTON) {
      string res=uis[currentUI]->MouseInputEvent(0,0,true);
      LogMouseInput(res);
    }
  }

  virtual void DoFreeDrag(int dx,int dy,int button)
  {
    if(button == GLUT_LEFT_BUTTON)  DragRotate(dx,dy);
    else if(button == GLUT_RIGHT_BUTTON) {
      string res=uis[currentUI]->MouseInputEvent(dx,dy,true);
      LogMouseInput(res);
    }
  }

  virtual void DoCtrlDrag(int dx,int dy,int button)
  {
    if(button == GLUT_LEFT_BUTTON)  DragPan(dx,dy);
  }

  virtual void DoAltDrag(int dx,int dy,int button)
  {
    if(button == GLUT_LEFT_BUTTON)  DragZoom(dx,dy);
  }

  virtual void DoShiftDrag(int dx,int dy,int button)
  {
    if(button == GLUT_LEFT_BUTTON) { camera.dist *= (1 + 0.01*Real(dy)); }
  }

  virtual void Handle_Motion(int x,int y)
  {
    string res=uis[currentUI]->MouseInputEvent(x,y,false);
    LogMouseInput(res);
    Refresh();
  }

  virtual void Handle_Keypress(unsigned char key,int x,int y)
  {
    string res=uis[currentUI]->KeypressEvent(key,x,y);
    LogKeypress(res);
    Refresh();
  }

  virtual void Handle_Idle() {
    if(simulate) {
      Timer timer;
      string res=uis[currentUI]->UpdateEvent();
      LogUpdate(res);

      sim.Advance(dt);
      Refresh();

      SleepIdleCallback(int(Max(0.0,dt-timer.ElapsedTime())*1000.0));
    }
    WorldViewProgram::Handle_Idle();
  }
};

int main(int argc, char** argv)
{
  if(argc < 2) {
    printf("USAGE: UserTrials XML_file [log file]\n");
    return 0;
  }
  RobotWorld world;
  world.lights.resize(1);
  world.lights[0].setColor(GLColor(1,1,1));
  world.lights[0].setDirectionalLight(Vector3(0.2,-0.4,1));
  world.lights[0].setColor(GLColor(1,1,1));

  XmlWorld xmlWorld;
  char* logFile = NULL;
  for(int i=1;i<argc;i++) {
    const char* ext=FileExtension(argv[i]);
    if(0==strcmp(ext,"rob")) {
      if(world.LoadRobot(argv[i])<0) {
	printf("Error loading robot file %s\n",argv[i]);
	return 1;
      }
    }
    else if(0==strcmp(ext,"env") || 0==strcmp(ext,"tri")) {
      if(world.LoadTerrain(argv[i])<0) {
	printf("Error loading terrain file %s\n",argv[i]);
	return 1;
      }
    }
    else if(0==strcmp(ext,"obj")) {
      if(world.LoadRigidObject(argv[i])<0) {
	printf("Error loading rigid object file %s\n",argv[i]);
	return 1;
      }
    }
    else if(0==strcmp(ext,"xml")) {
      if(!xmlWorld.Load(argv[i])) {
	printf("Error loading world file %s\n",argv[i]);
	return 1;
      }
      if(!xmlWorld.GetWorld(world)) {
	printf("Error loading world from %s\n",argv[i]);
	return 1;
      }
    }
    else if(0==strcmp(ext,"log")) {
      logFile = argv[i];
    }
    else {
      printf("Unknown file extension %s on file %s\n",ext,argv[i]);
      return 1;
    }
  }

  UserTrialProgram program(&world);
  if(logFile) program.logFile = logFile;
  program.InitSim();

  stringstream params;
  for(int i=1;i<argc;i++)
    params<<argv[i]<<" ";
  program.LogBegin(params.str());
  return program.Run();
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <cstddef>
#include <sstream>
#include <Context.h>
#include <text.h>
#include <i18n.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
void legacyAttributeCheck (const std::string& name)
{
  // 2013-07-25: Deprecated "fg" and "bg" removed.
}

////////////////////////////////////////////////////////////////////////////////
void legacyColumnMap (std::string& name)
{
  // 2014-01-26: priority_long        --> priority.long        Mapping removed
  // 2014-01-26: entry_time           --> entry                Mapping removed
  // 2014-01-26: start_time           --> start                Mapping removed
  // 2014-01-26: end_time             --> end                  Mapping removed
  // 2014-01-26: countdown            --> due.countdown        Mapping removed
  // 2014-01-26: countdown_compact    --> due.countdown        Mapping removed
  // 2014-01-26: age                  --> entry.age            Mapping removed
  // 2014-01-26: age_compact          --> entry.age            Mapping removed
  // 2014-01-26: active               --> start.active         Mapping removed
  // 2014-01-26: recurrence_indicator --> recur.indicator      Mapping removed
  // 2014-01-26: tag_indicator        --> tags.indicator       Mapping removed
  // 2014-01-26: description_only     --> description.desc     Mapping removed
}

////////////////////////////////////////////////////////////////////////////////
void legacySortColumnMap (std::string& name)
{
  // 2014-01-26: priority_long        --> priority             Mapping removed
  // 2014-01-26: entry_time           --> entry                Mapping removed
  // 2014-01-26: start_time           --> start                Mapping removed
  // 2014-01-26: end_time             --> end                  Mapping removed
  // 2014-01-26: countdown            --> due                  Mapping removed
  // 2014-01-26: countdown_compact    --> due                  Mapping removed
  // 2014-01-26: age                  --> entry                Mapping removed
  // 2014-01-26: age_compact          --> entry                Mapping removed
  // 2014-01-26: active               --> start                Mapping removed
  // 2014-01-26: recurrence_indicator --> recur                Mapping removed
  // 2014-01-26: tag_indicator        --> tags                 Mapping removed
  // 2014-01-26: description_only     --> description          Mapping removed
}

////////////////////////////////////////////////////////////////////////////////
std::string legacyCheckForDeprecatedColor ()
{
  // 2014-01-26: Color defs containing '_' removed.

  return "";
}

////////////////////////////////////////////////////////////////////////////////
std::string legacyCheckForDeprecatedVariables ()
{
  std::vector <std::string> deprecated;
  std::map <std::string, std::string>::const_iterator it;
  for (it = context.config.begin (); it != context.config.end (); ++it)
  {
    // 2014-07-04: report.*.limit removed.

    // report.*.annotations
    if (it->first.length () > 19 &&
        it->first.substr (0, 7) == "report." &&
        it->first.substr (it->first.length () - 12) == ".annotations")
      deprecated.push_back (it->first);

    if (it->first == "next"              ||
        it->first == "annotations"       ||
        it->first == "export.ical.class")
      deprecated.push_back (it->first);

    // Deprecated іn 2.4.0.
    if (it->first == "alias._query")
      deprecated.push_back (it->first);
  }

  std::stringstream out;
  if (deprecated.size ())
  {
    out << STRING_CONFIG_DEPRECATED_VAR
        << "\n";

    std::vector <std::string>::iterator it2;
    for (it2 = deprecated.begin (); it2 != deprecated.end (); ++it2)
      out << "  " << *it2 << "\n";

    out << "\n";
  }

  return out.str ();
}

////////////////////////////////////////////////////////////////////////////////
std::string legacyCheckForDeprecatedColumns ()
{
  std::vector <std::string> deprecated;
  std::map <std::string, std::string>::const_iterator it;
  for (it = context.config.begin (); it != context.config.end (); ++it)
  {
    if (it->first.find ("report") == 0)
    {
      std::string value = context.config.get (it->first);
      if (value.find ("entry_time") != std::string::npos ||
          value.find ("start_time") != std::string::npos ||
          value.find ("end_time")   != std::string::npos)
        deprecated.push_back (it->first);
    }
  }

  std::stringstream out;
  out << "\n";

  if (deprecated.size ())
  {
    out << STRING_CONFIG_DEPRECATED_COL
        << "\n";

    std::vector <std::string>::iterator it2;
    for (it2 = deprecated.begin (); it2 != deprecated.end (); ++it2)
      out << "  " << *it2 << "=" << context.config.get (*it2) << "\n";

    out << "\n";
  }

  return out.str ();
}

////////////////////////////////////////////////////////////////////////////////
void legacyAttributeMap (std::string& name)
{
  // TW-1274
  if (name == "modification")
    name = "modified";
}

////////////////////////////////////////////////////////////////////////////////
void legacyValueMap (const std::string& name, std::string& value)
{
  // 2014-07-03: One-time initialization value mapping.
  static std::map <std::string, std::string> mapping;
  if (mapping.size () == 0)
  {
    mapping["hrs"]   = "hours";
    mapping["hrs"]   = "hours";
    mapping["hr"]    = "hours";
    mapping["mins"]  = "minutes";
    mapping["mnths"] = "months";
    mapping["mths"]  = "months";
    mapping["mth"]   = "months";
    mapping["mos"]   = "months";
    mapping["m"]     = "months";
    mapping["qrtrs"] = "quarters";
    mapping["qtrs"]  = "quarters";
    mapping["qtr"]   = "quarters";
    mapping["secs"]  = "seconds";
    mapping["sec"]   = "seconds";
    mapping["s"]     = "seconds";
    mapping["wks"]   = "weeks";
    mapping["wk"]    = "weeks";
    mapping["yrs"]   = "years";
    mapping["yr"]    = "years";
  }

  if (name == "recur")
  {
    std::size_t letter = value.find_first_not_of ("0123456789.");
    if (letter == std::string::npos)
      letter = 0;

    std::map <std::string, std::string>::iterator i = mapping.find (value.substr (letter));
    if (i != mapping.end ())
    {
      if (letter)
        value = value.substr (0, letter) + i->second;
      else
        value = i->second;
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>Cleanup<commit_after>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <cstddef>
#include <sstream>
#include <Context.h>
#include <text.h>
#include <i18n.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
void legacyAttributeCheck (const std::string& name)
{
  // 2013-07-25: Deprecated "fg" and "bg" removed.
}

////////////////////////////////////////////////////////////////////////////////
void legacyColumnMap (std::string& name)
{
  // 2014-01-26: priority_long        --> priority.long        Mapping removed
  // 2014-01-26: entry_time           --> entry                Mapping removed
  // 2014-01-26: start_time           --> start                Mapping removed
  // 2014-01-26: end_time             --> end                  Mapping removed
  // 2014-01-26: countdown            --> due.countdown        Mapping removed
  // 2014-01-26: countdown_compact    --> due.countdown        Mapping removed
  // 2014-01-26: age                  --> entry.age            Mapping removed
  // 2014-01-26: age_compact          --> entry.age            Mapping removed
  // 2014-01-26: active               --> start.active         Mapping removed
  // 2014-01-26: recurrence_indicator --> recur.indicator      Mapping removed
  // 2014-01-26: tag_indicator        --> tags.indicator       Mapping removed
  // 2014-01-26: description_only     --> description.desc     Mapping removed
}

////////////////////////////////////////////////////////////////////////////////
void legacySortColumnMap (std::string& name)
{
  // 2014-01-26: priority_long        --> priority             Mapping removed
  // 2014-01-26: entry_time           --> entry                Mapping removed
  // 2014-01-26: start_time           --> start                Mapping removed
  // 2014-01-26: end_time             --> end                  Mapping removed
  // 2014-01-26: countdown            --> due                  Mapping removed
  // 2014-01-26: countdown_compact    --> due                  Mapping removed
  // 2014-01-26: age                  --> entry                Mapping removed
  // 2014-01-26: age_compact          --> entry                Mapping removed
  // 2014-01-26: active               --> start                Mapping removed
  // 2014-01-26: recurrence_indicator --> recur                Mapping removed
  // 2014-01-26: tag_indicator        --> tags                 Mapping removed
  // 2014-01-26: description_only     --> description          Mapping removed
}

////////////////////////////////////////////////////////////////////////////////
std::string legacyCheckForDeprecatedColor ()
{
  // 2014-01-26: Color defs containing '_' removed.

  return "";
}

////////////////////////////////////////////////////////////////////////////////
std::string legacyCheckForDeprecatedVariables ()
{
  std::vector <std::string> deprecated;
  std::map <std::string, std::string>::const_iterator it;
  for (it = context.config.begin (); it != context.config.end (); ++it)
  {
    // 2014-07-04: report.*.limit removed.

    // report.*.annotations
    if (it->first.length () > 19 &&
        it->first.substr (0, 7) == "report." &&
        it->first.substr (it->first.length () - 12) == ".annotations")
      deprecated.push_back (it->first);

    if (it->first == "next"              ||
        it->first == "annotations"       ||
        it->first == "export.ical.class")
      deprecated.push_back (it->first);

    // Deprecated іn 2.4.0.
    if (it->first == "alias._query")
      deprecated.push_back (it->first);
  }

  std::stringstream out;
  if (deprecated.size ())
  {
    out << STRING_CONFIG_DEPRECATED_VAR
        << "\n";

    std::vector <std::string>::iterator it2;
    for (it2 = deprecated.begin (); it2 != deprecated.end (); ++it2)
      out << "  " << *it2 << "\n";

    out << "\n";
  }

  return out.str ();
}

////////////////////////////////////////////////////////////////////////////////
std::string legacyCheckForDeprecatedColumns ()
{
  std::vector <std::string> deprecated;
  std::map <std::string, std::string>::const_iterator it;
  for (it = context.config.begin (); it != context.config.end (); ++it)
  {
    if (it->first.find ("report") == 0)
    {
      std::string value = context.config.get (it->first);
      if (value.find ("entry_time") != std::string::npos ||
          value.find ("start_time") != std::string::npos ||
          value.find ("end_time")   != std::string::npos)
        deprecated.push_back (it->first);
    }
  }

  std::stringstream out;
  out << "\n";

  if (deprecated.size ())
  {
    out << STRING_CONFIG_DEPRECATED_COL
        << "\n";

    std::vector <std::string>::iterator it2;
    for (it2 = deprecated.begin (); it2 != deprecated.end (); ++it2)
      out << "  " << *it2 << "=" << context.config.get (*it2) << "\n";

    out << "\n";
  }

  return out.str ();
}

////////////////////////////////////////////////////////////////////////////////
void legacyAttributeMap (std::string& name)
{
  // TW-1274, 2.4.0
  if (name == "modification")
    name = "modified";
}

////////////////////////////////////////////////////////////////////////////////
// TODO Is this needed, given Task::upgradeLegacyValues?
void legacyValueMap (const std::string& name, std::string& value)
{
  // 2014-07-03: One-time initialization value mapping.
  static std::map <std::string, std::string> mapping;
  if (mapping.size () == 0)
  {
    mapping["hrs"]   = "hours";
    mapping["hr"]    = "hours";
    mapping["mins"]  = "minutes";
    mapping["mnths"] = "months";
    mapping["mths"]  = "months";
    mapping["mth"]   = "months";
    mapping["mos"]   = "months";
    mapping["m"]     = "months";   // ?
    mapping["qrtrs"] = "quarters";
    mapping["qtrs"]  = "quarters";
    mapping["qtr"]   = "quarters";
    mapping["secs"]  = "seconds";
    mapping["sec"]   = "seconds";
    mapping["s"]     = "seconds";  // ?
    mapping["wks"]   = "weeks";
    mapping["wk"]    = "weeks";
    mapping["yrs"]   = "years";
    mapping["yr"]    = "years";
  }

  if (name == "recur")
  {
    std::size_t letter = value.find_first_not_of ("0123456789.");
    if (letter == std::string::npos)
      letter = 0;

    std::map <std::string, std::string>::iterator i = mapping.find (value.substr (letter));
    if (i != mapping.end ())
    {
      if (letter)
        value = value.substr (0, letter) + i->second;
      else
        value = i->second;
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>