<commit_before>/**************************************************************************
** This file is part of LiteIDE
**
** Copyright (c) 2011-2014 LiteIDE Team. All rights reserved.
**
** 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.
**
** In addition, as a special exception,  that plugins developed for LiteIDE,
** are allowed to remain closed sourced and can be distributed under any license .
** These rights are included in the file LGPL_EXCEPTION.txt in this package.
**
**************************************************************************/
// Module: tooldockwidget.cpp
// Creator: visualfc <visualfc@gmail.com>

#include "tooldockwidget.h"
#include "liteapi/liteapi.h"
#include <QAction>
#include <QIcon>
#include <QLabel>
#include <QHBoxLayout>
#include <QVariant>
#include <QMenu>
#include <QToolButton>
#include <QDebug>
//lite_memory_check_begin
#if defined(WIN32) && defined(_MSC_VER) &&  defined(_DEBUG)
     #define _CRTDBG_MAP_ALLOC
     #include <stdlib.h>
     #include <crtdbg.h>
     #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
     #define new DEBUG_NEW
#endif
//lite_memory_check_end

ToolDockWidget::ToolDockWidget(QSize iconSize, QWidget *parent) :
    QDockWidget(parent), current(0)
{
    m_comboBox = new QComboBox;
    m_comboBox->setMinimumContentsLength(4);
    m_comboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);

    m_toolBar = new QToolBar(this);
    m_toolBar->setContentsMargins(0, 0, 0, 0);
    m_toolBar->setIconSize(iconSize);
    //m_toolBar->setFixedHeight(24);
    m_toolBar->addWidget(m_comboBox);

    QWidget *spacer = new QWidget;
    spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
    m_toolBar->addSeparator();
    m_spacerAct = m_toolBar->addWidget(spacer);

    m_closeAct = new QAction(tr("Hide"), m_toolBar);
    m_closeAct->setToolTip(tr("Hide Tool Window"));
    m_closeAct->setIcon(QIcon("icon:images/closetool.png"));
    m_toolBar->addAction(m_closeAct);
    connect(m_closeAct,SIGNAL(triggered()),this,SLOT(close()));
    connect(m_comboBox,SIGNAL(activated(int)),this,SLOT(activeComboBoxIndex(int)));

    this->setTitleBarWidget(m_toolBar);
/*
    m_toolBar->setStyleSheet("QToolBar {border: 1px ; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #eeeeee, stop: 1 #ababab); }"\
                             "QToolBar QToolButton { border:1px ; border-radius: 1px; }"\
                             "QToolBar QToolButton::hover { background-color: #ababab;}"\
                             "QToolBar::separator {width:2px; margin-left:2px; margin-right:2px; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #dedede, stop: 1 #a0a0a0);}");
*/
}

void ToolDockWidget::createMenu(Qt::DockWidgetArea area, bool split)
{
    QMenu *moveMenu = new QMenu(tr("Move To"),this);
    if (area != Qt::TopDockWidgetArea) {
        QAction *act = new QAction(tr("Top"),this);
        act->setData(Qt::TopDockWidgetArea);
        moveMenu->addAction(act);
        connect(act,SIGNAL(triggered()),this,SLOT(moveAction()));
        QAction *act1 = new QAction(tr("Top (Split)"),this);
        act1->setData(Qt::TopDockWidgetArea);
        moveMenu->addAction(act1);
        connect(act1,SIGNAL(triggered()),this,SLOT(moveActionSplit()));
    }
    if (area != Qt::BottomDockWidgetArea) {
        QAction *act = new QAction(tr("Bottom"),this);
        act->setData(Qt::BottomDockWidgetArea);
        moveMenu->addAction(act);
        connect(act,SIGNAL(triggered()),this,SLOT(moveAction()));
        QAction *act1 = new QAction(tr("Bottom (Split)"),this);
        act1->setData(Qt::BottomDockWidgetArea);
        moveMenu->addAction(act1);
        connect(act1,SIGNAL(triggered()),this,SLOT(moveActionSplit()));
    }
    if (area != Qt::LeftDockWidgetArea) {
        QAction *act = new QAction(tr("Left"),this);
        act->setData(Qt::LeftDockWidgetArea);
        moveMenu->addAction(act);
        connect(act,SIGNAL(triggered()),this,SLOT(moveAction()));
        QAction *act1 = new QAction(tr("Left (Split)"),this);
        act1->setData(Qt::LeftDockWidgetArea);
        moveMenu->addAction(act1);
        connect(act1,SIGNAL(triggered()),this,SLOT(moveActionSplit()));
    }
    if (area != Qt::RightDockWidgetArea) {
        QAction *act = new QAction(tr("Right"),this);
        act->setData(Qt::RightDockWidgetArea);
        moveMenu->addAction(act);
        connect(act,SIGNAL(triggered()),this,SLOT(moveAction()));
        QAction *act1 = new QAction(tr("Right (Split)"),this);
        act1->setData(Qt::RightDockWidgetArea);
        moveMenu->addAction(act1);
        connect(act1,SIGNAL(triggered()),this,SLOT(moveActionSplit()));
    }

    QMenu *menu = new QMenu(this);
    if (split) {
        QAction *unsplitAct = new QAction(tr("Unsplit"),this);
        unsplitAct->setData(area);
        connect(unsplitAct,SIGNAL(triggered()),this,SLOT(unsplitAction()));
        menu->addAction(unsplitAct);
    } else {
        QAction *splitAct = new QAction(tr("Split"),this);
        splitAct->setData(area);
        connect(splitAct,SIGNAL(triggered()),this,SLOT(splitAction()));
        menu->addAction(splitAct);
    }
    menu->addAction(moveMenu->menuAction());

    QToolButton *btn = new QToolButton(m_toolBar);
    btn->setPopupMode(QToolButton::InstantPopup);
    btn->setIcon(QIcon("icon:images/movemenu.png"));
    btn->setMenu(menu);
    btn->setText(tr("Move To"));
    btn->setToolTip(tr("Move To"));
    //btn->setStyleSheet("QToolButton::menu-indicator {image: none;}");
    m_toolBar->insertWidget(m_closeAct,btn);
}

void ToolDockWidget::moveAction()
{
    QAction *action = static_cast<QAction*>(sender());
    if (!action) {
        return;
    }
    Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt();
    emit moveActionTo(area,current,false);
}

void ToolDockWidget::moveActionSplit()
{
    QAction *action = static_cast<QAction*>(sender());
    if (!action) {
        return;
    }
    Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt();
    emit moveActionTo(area,current,true);
}

void ToolDockWidget::splitAction()
{
    QAction *action = static_cast<QAction*>(sender());
    if (!action) {
        return;
    }
    Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt();
    emit moveActionTo(area,current,true);
}

void ToolDockWidget::unsplitAction()
{
    QAction *action = static_cast<QAction*>(sender());
    if (!action) {
        return;
    }
    Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt();
    emit moveActionTo(area,current,false);
}

void ToolDockWidget::setWindowTitle(const QString &text)
{
    QDockWidget::setWindowTitle(text);
}

QAction *ToolDockWidget::addWidget(QWidget *widget)
{
   return m_toolBar->insertWidget(m_closeAct,widget);
}

void ToolDockWidget::setToolMenu(QMenu *menu)
{
    QToolButton *btn = new QToolButton;
    btn->setPopupMode(QToolButton::InstantPopup);
    btn->setMenu(menu);

    m_toolBar->insertWidget(m_closeAct,btn);
}

void ToolDockWidget::setWidgetActions(QList<QAction*> actions)
{
    foreach(QAction *action, m_widgetActions) {
        m_toolBar->removeAction(action);
    }
    m_widgetActions = actions;
    m_spacerAct->setVisible(!m_widgetActions.isEmpty());
    foreach(QAction *action, m_widgetActions) {
        m_toolBar->insertAction(m_spacerAct,action);
        if (action->menu() != 0) {
            QWidget *w = m_toolBar->widgetForAction(action);
            QToolButton *btn = qobject_cast<QToolButton*>(w);
            if (btn) {
                btn->setPopupMode(QToolButton::InstantPopup);
            }
        }
    }
}

QList<QAction *> ToolDockWidget::actions() const
{
    return m_actions;
}

void ToolDockWidget::removeAction(QAction *action)
{
    if (m_actions.removeAll(action)) {
        if (action == current)
            current = 0;
        int index = m_comboBox->findData(action->objectName());
        if (index >= 0) {
            m_comboBox->removeItem(index);
        }
        QObject::disconnect(action, SIGNAL(changed()), this, SLOT(actionChanged()));
    }
}

QAction * ToolDockWidget::checkedAction () const
{
    return current;
}

void ToolDockWidget::actionChanged()
{
    QAction *action = qobject_cast<QAction*>(sender());
    Q_ASSERT_X(action != 0, "ActionGroup::actionChanged", "internal error");
    if (action->isChecked()) {
        if (action != current) {
            if(current)
                current->setChecked(false);
            current = action;
            int index = m_comboBox->findData(action->objectName());
            if (index >= 0) {
                m_comboBox->setCurrentIndex(index);
            }
        }
    } else if (action == current) {
        current = 0;
    }
}

void ToolDockWidget::activeComboBoxIndex(int index)
{
    if (index < 0 || index >= m_comboBox->count()) {
        return;
    }
    QString objName = m_comboBox->itemData(index).toString();
    foreach(QAction *act, m_actions) {
        if (act->objectName() == objName) {
            if (!act->isChecked()) {
                act->setChecked(true);
            }
            break;
        }
    }
}

void ToolDockWidget::addAction(QAction *action, const QString &title)
{
    if(!m_actions.contains(action)) {
        m_actions.append(action);
        m_comboBox->addItem(title,action->objectName());
        QObject::connect(action, SIGNAL(changed()), this, SLOT(actionChanged()));
    }
    if (current && current->isChecked()) {
        current->setChecked(false);
    }
    if (action->isChecked()) {
        current = action;
    }
}

<commit_msg>update split dock title<commit_after>/**************************************************************************
** This file is part of LiteIDE
**
** Copyright (c) 2011-2014 LiteIDE Team. All rights reserved.
**
** 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.
**
** In addition, as a special exception,  that plugins developed for LiteIDE,
** are allowed to remain closed sourced and can be distributed under any license .
** These rights are included in the file LGPL_EXCEPTION.txt in this package.
**
**************************************************************************/
// Module: tooldockwidget.cpp
// Creator: visualfc <visualfc@gmail.com>

#include "tooldockwidget.h"
#include "liteapi/liteapi.h"
#include <QAction>
#include <QIcon>
#include <QLabel>
#include <QHBoxLayout>
#include <QVariant>
#include <QMenu>
#include <QToolButton>
#include <QDebug>
//lite_memory_check_begin
#if defined(WIN32) && defined(_MSC_VER) &&  defined(_DEBUG)
     #define _CRTDBG_MAP_ALLOC
     #include <stdlib.h>
     #include <crtdbg.h>
     #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
     #define new DEBUG_NEW
#endif
//lite_memory_check_end

ToolDockWidget::ToolDockWidget(QSize iconSize, QWidget *parent) :
    QDockWidget(parent), current(0)
{
    m_comboBox = new QComboBox;
    m_comboBox->setMinimumContentsLength(4);
    //m_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
    m_comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);

    m_toolBar = new QToolBar(this);
    m_toolBar->setContentsMargins(0, 0, 0, 0);
    m_toolBar->setIconSize(iconSize);
    //m_toolBar->setFixedHeight(24);
    m_toolBar->addWidget(m_comboBox);

    QWidget *spacer = new QWidget;
    spacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
    m_toolBar->addSeparator();
    m_spacerAct = m_toolBar->addWidget(spacer);

    m_closeAct = new QAction(tr("Hide"), m_toolBar);
    m_closeAct->setToolTip(tr("Hide Tool Window"));
    m_closeAct->setIcon(QIcon("icon:images/closetool.png"));
    m_toolBar->addAction(m_closeAct);
    connect(m_closeAct,SIGNAL(triggered()),this,SLOT(close()));
    connect(m_comboBox,SIGNAL(activated(int)),this,SLOT(activeComboBoxIndex(int)));

    this->setTitleBarWidget(m_toolBar);
/*
    m_toolBar->setStyleSheet("QToolBar {border: 1px ; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #eeeeee, stop: 1 #ababab); }"\
                             "QToolBar QToolButton { border:1px ; border-radius: 1px; }"\
                             "QToolBar QToolButton::hover { background-color: #ababab;}"\
                             "QToolBar::separator {width:2px; margin-left:2px; margin-right:2px; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #dedede, stop: 1 #a0a0a0);}");
*/
}

void ToolDockWidget::createMenu(Qt::DockWidgetArea area, bool split)
{
    QMenu *moveMenu = new QMenu(tr("Move To"),this);
    if (area != Qt::TopDockWidgetArea) {
        QAction *act = new QAction(tr("Top"),this);
        act->setData(Qt::TopDockWidgetArea);
        moveMenu->addAction(act);
        connect(act,SIGNAL(triggered()),this,SLOT(moveAction()));
        QAction *act1 = new QAction(tr("Top (Split)"),this);
        act1->setData(Qt::TopDockWidgetArea);
        moveMenu->addAction(act1);
        connect(act1,SIGNAL(triggered()),this,SLOT(moveActionSplit()));
    }
    if (area != Qt::BottomDockWidgetArea) {
        QAction *act = new QAction(tr("Bottom"),this);
        act->setData(Qt::BottomDockWidgetArea);
        moveMenu->addAction(act);
        connect(act,SIGNAL(triggered()),this,SLOT(moveAction()));
        QAction *act1 = new QAction(tr("Bottom (Split)"),this);
        act1->setData(Qt::BottomDockWidgetArea);
        moveMenu->addAction(act1);
        connect(act1,SIGNAL(triggered()),this,SLOT(moveActionSplit()));
    }
    if (area != Qt::LeftDockWidgetArea) {
        QAction *act = new QAction(tr("Left"),this);
        act->setData(Qt::LeftDockWidgetArea);
        moveMenu->addAction(act);
        connect(act,SIGNAL(triggered()),this,SLOT(moveAction()));
        QAction *act1 = new QAction(tr("Left (Split)"),this);
        act1->setData(Qt::LeftDockWidgetArea);
        moveMenu->addAction(act1);
        connect(act1,SIGNAL(triggered()),this,SLOT(moveActionSplit()));
    }
    if (area != Qt::RightDockWidgetArea) {
        QAction *act = new QAction(tr("Right"),this);
        act->setData(Qt::RightDockWidgetArea);
        moveMenu->addAction(act);
        connect(act,SIGNAL(triggered()),this,SLOT(moveAction()));
        QAction *act1 = new QAction(tr("Right (Split)"),this);
        act1->setData(Qt::RightDockWidgetArea);
        moveMenu->addAction(act1);
        connect(act1,SIGNAL(triggered()),this,SLOT(moveActionSplit()));
    }

    QMenu *menu = new QMenu(this);
    if (split) {
        QAction *unsplitAct = new QAction(tr("Unsplit"),this);
        unsplitAct->setData(area);
        connect(unsplitAct,SIGNAL(triggered()),this,SLOT(unsplitAction()));
        menu->addAction(unsplitAct);
    } else {
        QAction *splitAct = new QAction(tr("Split"),this);
        splitAct->setData(area);
        connect(splitAct,SIGNAL(triggered()),this,SLOT(splitAction()));
        menu->addAction(splitAct);
    }
    menu->addAction(moveMenu->menuAction());

    if (area == Qt::BottomDockWidgetArea || area == Qt::TopDockWidgetArea) {
        m_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
        m_comboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
        QWidget *spacer = new QWidget;
        spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
        m_toolBar->insertWidget(m_closeAct,spacer);
    }

    QToolButton *btn = new QToolButton(m_toolBar);
    btn->setPopupMode(QToolButton::InstantPopup);
    btn->setIcon(QIcon("icon:images/movemenu.png"));
    btn->setMenu(menu);
    btn->setText(tr("Move To"));
    btn->setToolTip(tr("Move To"));
    //btn->setStyleSheet("QToolButton::menu-indicator {image: none;}");
    m_toolBar->insertWidget(m_closeAct,btn);
}

void ToolDockWidget::moveAction()
{
    QAction *action = static_cast<QAction*>(sender());
    if (!action) {
        return;
    }
    Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt();
    emit moveActionTo(area,current,false);
}

void ToolDockWidget::moveActionSplit()
{
    QAction *action = static_cast<QAction*>(sender());
    if (!action) {
        return;
    }
    Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt();
    emit moveActionTo(area,current,true);
}

void ToolDockWidget::splitAction()
{
    QAction *action = static_cast<QAction*>(sender());
    if (!action) {
        return;
    }
    Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt();
    emit moveActionTo(area,current,true);
}

void ToolDockWidget::unsplitAction()
{
    QAction *action = static_cast<QAction*>(sender());
    if (!action) {
        return;
    }
    Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt();
    emit moveActionTo(area,current,false);
}

void ToolDockWidget::setWindowTitle(const QString &text)
{
    QDockWidget::setWindowTitle(text);
}

QAction *ToolDockWidget::addWidget(QWidget *widget)
{
   return m_toolBar->insertWidget(m_closeAct,widget);
}

void ToolDockWidget::setToolMenu(QMenu *menu)
{
    QToolButton *btn = new QToolButton;
    btn->setPopupMode(QToolButton::InstantPopup);
    btn->setMenu(menu);

    m_toolBar->insertWidget(m_closeAct,btn);
}

void ToolDockWidget::setWidgetActions(QList<QAction*> actions)
{
    foreach(QAction *action, m_widgetActions) {
        m_toolBar->removeAction(action);
    }
    m_widgetActions = actions;
    m_spacerAct->setVisible(!m_widgetActions.isEmpty());
    foreach(QAction *action, m_widgetActions) {
        m_toolBar->insertAction(m_spacerAct,action);
        if (action->menu() != 0) {
            QWidget *w = m_toolBar->widgetForAction(action);
            QToolButton *btn = qobject_cast<QToolButton*>(w);
            if (btn) {
                btn->setPopupMode(QToolButton::InstantPopup);
            }
        }
    }
}

QList<QAction *> ToolDockWidget::actions() const
{
    return m_actions;
}

void ToolDockWidget::removeAction(QAction *action)
{
    if (m_actions.removeAll(action)) {
        if (action == current)
            current = 0;
        int index = m_comboBox->findData(action->objectName());
        if (index >= 0) {
            m_comboBox->removeItem(index);
        }
        QObject::disconnect(action, SIGNAL(changed()), this, SLOT(actionChanged()));
    }
}

QAction * ToolDockWidget::checkedAction () const
{
    return current;
}

void ToolDockWidget::actionChanged()
{
    QAction *action = qobject_cast<QAction*>(sender());
    Q_ASSERT_X(action != 0, "ActionGroup::actionChanged", "internal error");
    if (action->isChecked()) {
        if (action != current) {
            if(current)
                current->setChecked(false);
            current = action;
            int index = m_comboBox->findData(action->objectName());
            if (index >= 0) {
                m_comboBox->setCurrentIndex(index);
            }
        }
    } else if (action == current) {
        current = 0;
    }
}

void ToolDockWidget::activeComboBoxIndex(int index)
{
    if (index < 0 || index >= m_comboBox->count()) {
        return;
    }
    QString objName = m_comboBox->itemData(index).toString();
    foreach(QAction *act, m_actions) {
        if (act->objectName() == objName) {
            if (!act->isChecked()) {
                act->setChecked(true);
            }
            break;
        }
    }
}

void ToolDockWidget::addAction(QAction *action, const QString &title)
{
    if(!m_actions.contains(action)) {
        m_actions.append(action);
        m_comboBox->addItem(title,action->objectName());
        QObject::connect(action, SIGNAL(changed()), this, SLOT(actionChanged()));
    }
    if (current && current->isChecked()) {
        current->setChecked(false);
    }
    if (action->isChecked()) {
        current = action;
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/native_entry.h"

#include "include/dart_api.h"

#include "vm/bootstrap.h"
#include "vm/code_patcher.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_api_state.h"
#include "vm/native_symbol.h"
#include "vm/object_store.h"
#include "vm/reusable_handles.h"
#include "vm/safepoint.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/tags.h"

namespace dart {

DEFINE_FLAG(bool,
            trace_natives,
            false,
            "Trace invocation of natives (debug mode only)");

void DartNativeThrowArgumentException(const Instance& instance) {
  const Array& __args__ = Array::Handle(Array::New(1));
  __args__.SetAt(0, instance);
  Exceptions::ThrowByType(Exceptions::kArgument, __args__);
}

NativeFunction NativeEntry::ResolveNative(const Library& library,
                                          const String& function_name,
                                          int number_of_arguments,
                                          bool* auto_setup_scope) {
  // Now resolve the native function to the corresponding native entrypoint.
  if (library.native_entry_resolver() == 0) {
    // Native methods are not allowed in the library to which this
    // class belongs in.
    return NULL;
  }
  Dart_NativeFunction native_function = NULL;
  {
    Thread* T = Thread::Current();
    TransitionVMToNative transition(T);
    Dart_EnterScope();  // Enter a new Dart API scope as we invoke API entries.
    Dart_NativeEntryResolver resolver = library.native_entry_resolver();
    native_function = resolver(Api::NewHandle(T, function_name.raw()),
                               number_of_arguments, auto_setup_scope);
    Dart_ExitScope();  // Exit the Dart API scope.
  }
  return reinterpret_cast<NativeFunction>(native_function);
}

const uint8_t* NativeEntry::ResolveSymbolInLibrary(const Library& library,
                                                   uword pc) {
  Dart_NativeEntrySymbol symbol_resolver =
      library.native_entry_symbol_resolver();
  if (symbol_resolver == 0) {
    // Cannot reverse lookup native entries.
    return NULL;
  }
  return symbol_resolver(reinterpret_cast<Dart_NativeFunction>(pc));
}

const uint8_t* NativeEntry::ResolveSymbol(uword pc) {
  Thread* thread = Thread::Current();
  REUSABLE_GROWABLE_OBJECT_ARRAY_HANDLESCOPE(thread);
  GrowableObjectArray& libs = reused_growable_object_array_handle.Handle();
  libs ^= thread->isolate()->object_store()->libraries();
  ASSERT(!libs.IsNull());
  intptr_t num_libs = libs.Length();
  for (intptr_t i = 0; i < num_libs; i++) {
    REUSABLE_LIBRARY_HANDLESCOPE(thread);
    Library& lib = reused_library_handle.Handle();
    lib ^= libs.At(i);
    ASSERT(!lib.IsNull());
    const uint8_t* r = ResolveSymbolInLibrary(lib, pc);
    if (r != NULL) {
      return r;
    }
  }
  return NULL;
}

bool NativeEntry::ReturnValueIsError(NativeArguments* arguments) {
  RawObject* retval = arguments->ReturnValue();
  return (retval->IsHeapObject() &&
          RawObject::IsErrorClassId(retval->GetClassId()));
}

void NativeEntry::PropagateErrors(NativeArguments* arguments) {
  Thread* thread = arguments->thread();
  thread->UnwindScopes(thread->top_exit_frame_info());

  // The thread->zone() is different here than before we unwound.
  const Object& error =
      Object::Handle(thread->zone(), arguments->ReturnValue());
  Exceptions::PropagateError(Error::Cast(error));
  UNREACHABLE();
}

uword NativeEntry::NoScopeNativeCallWrapperEntry() {
  uword entry = reinterpret_cast<uword>(NativeEntry::NoScopeNativeCallWrapper);
#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
  // DBC does not use redirections unlike other simulators.
  entry = Simulator::RedirectExternalReference(
      entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments);
#endif
  return entry;
}

void NativeEntry::NoScopeNativeCallWrapper(Dart_NativeArguments args,
                                           Dart_NativeFunction func) {
  CHECK_STACK_ALIGNMENT;
  NoScopeNativeCallWrapperNoStackCheck(args, func);
}

void NativeEntry::NoScopeNativeCallWrapperNoStackCheck(
    Dart_NativeArguments args,
    Dart_NativeFunction func) {
  VERIFY_ON_TRANSITION;
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  /* Tell MemorySanitizer 'arguments' is initialized by generated code. */
  MSAN_UNPOISON(arguments, sizeof(*arguments));
  Thread* thread = arguments->thread();
  ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
  {
    TransitionGeneratedToNative transition(thread);
    func(args);
    if (ReturnValueIsError(arguments)) {
      PropagateErrors(arguments);
    }
  }
  ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
  VERIFY_ON_TRANSITION;
}

uword NativeEntry::AutoScopeNativeCallWrapperEntry() {
  uword entry =
      reinterpret_cast<uword>(NativeEntry::AutoScopeNativeCallWrapper);
#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
  // DBC does not use redirections unlike other simulators.
  entry = Simulator::RedirectExternalReference(
      entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments);
#endif
  return entry;
}

void NativeEntry::AutoScopeNativeCallWrapper(Dart_NativeArguments args,
                                             Dart_NativeFunction func) {
  CHECK_STACK_ALIGNMENT;
  AutoScopeNativeCallWrapperNoStackCheck(args, func);
}

void NativeEntry::AutoScopeNativeCallWrapperNoStackCheck(
    Dart_NativeArguments args,
    Dart_NativeFunction func) {
  VERIFY_ON_TRANSITION;
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  /* Tell MemorySanitizer 'arguments' is initialized by generated code. */
  MSAN_UNPOISON(arguments, sizeof(*arguments));
  Thread* thread = arguments->thread();
  ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
  {
    Isolate* isolate = thread->isolate();
    ApiState* state = isolate->api_state();
    ASSERT(state != NULL);
    ApiLocalScope* current_top_scope = thread->api_top_scope();
    ApiLocalScope* scope = thread->api_reusable_scope();
    TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func));
    TransitionGeneratedToNative transition(thread);
    if (scope == NULL) {
      scope =
          new ApiLocalScope(current_top_scope, thread->top_exit_frame_info());
      ASSERT(scope != NULL);
    } else {
      scope->Reinit(thread, current_top_scope, thread->top_exit_frame_info());
      thread->set_api_reusable_scope(NULL);
    }
    thread->set_api_top_scope(scope);  // New scope is now the top scope.

    func(args);
    if (ReturnValueIsError(arguments)) {
      PropagateErrors(arguments);
    }

    ASSERT(current_top_scope == scope->previous());
    thread->set_api_top_scope(current_top_scope);  // Reset top scope to prev.
    if (thread->api_reusable_scope() == NULL) {
      scope->Reset(thread);  // Reset the old scope which we just exited.
      thread->set_api_reusable_scope(scope);
    } else {
      ASSERT(thread->api_reusable_scope() != scope);
      delete scope;
    }
    DEOPTIMIZE_ALOT;
  }
  ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
  VERIFY_ON_TRANSITION;
}

// DBC does not support lazy native call linking.
#if !defined(TARGET_ARCH_DBC)
static NativeFunction ResolveNativeFunction(Zone* zone,
                                            const Function& func,
                                            bool* is_bootstrap_native,
                                            bool* is_auto_scope) {
  const Class& cls = Class::Handle(zone, func.Owner());
  const Library& library = Library::Handle(zone, cls.library());

  *is_bootstrap_native =
      Bootstrap::IsBootstapResolver(library.native_entry_resolver());

  const String& native_name = String::Handle(zone, func.native_name());
  ASSERT(!native_name.IsNull());

  const int num_params = NativeArguments::ParameterCountForResolution(func);
  return NativeEntry::ResolveNative(library, native_name, num_params,
                                    is_auto_scope);
}

uword NativeEntry::LinkNativeCallEntry() {
  uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall);
#if defined(USING_SIMULATOR)
  entry = Simulator::RedirectExternalReference(
      entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
#endif
  return entry;
}

void NativeEntry::LinkNativeCall(Dart_NativeArguments args) {
  CHECK_STACK_ALIGNMENT;
  VERIFY_ON_TRANSITION;
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  /* Tell MemorySanitizer 'arguments' is initialized by generated code. */
  MSAN_UNPOISON(arguments, sizeof(*arguments));
  TRACE_NATIVE_CALL("%s", "LinkNative");

  NativeFunction target_function = NULL;
  bool is_bootstrap_native = false;
  bool is_auto_scope = true;

  {
    TransitionGeneratedToVM transition(arguments->thread());
    StackZone stack_zone(arguments->thread());
    Zone* zone = stack_zone.GetZone();

    DartFrameIterator iterator(arguments->thread(),
                               StackFrameIterator::kNoCrossThreadIteration);
    StackFrame* caller_frame = iterator.NextFrame();

    const Code& code = Code::Handle(zone, caller_frame->LookupDartCode());
    const Function& func = Function::Handle(zone, code.function());

    if (FLAG_trace_natives) {
      THR_Print("Resolving native target for %s\n", func.ToCString());
    }

    target_function =
        ResolveNativeFunction(arguments->thread()->zone(), func,
                              &is_bootstrap_native, &is_auto_scope);
    ASSERT(target_function != NULL);

#if defined(DEBUG)
    {
      NativeFunction current_function = NULL;
      const Code& current_trampoline =
          Code::Handle(zone, CodePatcher::GetNativeCallAt(
                                 caller_frame->pc(), code, &current_function));
#if !defined(USING_SIMULATOR)
      ASSERT(current_function ==
             reinterpret_cast<NativeFunction>(LinkNativeCall));
#else
      ASSERT(
          current_function ==
          reinterpret_cast<NativeFunction>(Simulator::RedirectExternalReference(
              reinterpret_cast<uword>(LinkNativeCall),
              Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments)));
#endif
      ASSERT(current_trampoline.raw() ==
             StubCode::CallBootstrapNative_entry()->code());
    }
#endif

    NativeFunction patch_target_function = target_function;
    Code& trampoline = Code::Handle(zone);
    if (is_bootstrap_native) {
      trampoline = StubCode::CallBootstrapNative_entry()->code();
#if defined(USING_SIMULATOR)
      patch_target_function =
          reinterpret_cast<NativeFunction>(Simulator::RedirectExternalReference(
              reinterpret_cast<uword>(patch_target_function),
              Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments));
#endif
    } else if (is_auto_scope) {
      trampoline = StubCode::CallAutoScopeNative_entry()->code();
    } else {
      trampoline = StubCode::CallNoScopeNative_entry()->code();
    }

    CodePatcher::PatchNativeCallAt(caller_frame->pc(), code,
                                   patch_target_function, trampoline);

    if (FLAG_trace_natives) {
      THR_Print("    -> %p (%s)\n", target_function,
                is_bootstrap_native ? "bootstrap" : "non-bootstrap");
    }
  }
  VERIFY_ON_TRANSITION;

  // Tail-call resolved target.
  if (is_bootstrap_native) {
    target_function(arguments);
  } else if (is_auto_scope) {
    // Because this call is within a compilation unit, Clang doesn't respect
    // the ABI alignment here.
    NativeEntry::AutoScopeNativeCallWrapperNoStackCheck(
        args, reinterpret_cast<Dart_NativeFunction>(target_function));
  } else {
    // Because this call is within a compilation unit, Clang doesn't respect
    // the ABI alignment here.
    NativeEntry::NoScopeNativeCallWrapperNoStackCheck(
        args, reinterpret_cast<Dart_NativeFunction>(target_function));
  }
}
#endif  // !defined(TARGET_ARCH_DBC)

}  // namespace dart
<commit_msg>[vm] Fail more helpfully when invoking a null native function.<commit_after>// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/native_entry.h"

#include "include/dart_api.h"

#include "vm/bootstrap.h"
#include "vm/code_patcher.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_api_state.h"
#include "vm/native_symbol.h"
#include "vm/object_store.h"
#include "vm/reusable_handles.h"
#include "vm/safepoint.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/tags.h"

namespace dart {

DEFINE_FLAG(bool,
            trace_natives,
            false,
            "Trace invocation of natives (debug mode only)");

void DartNativeThrowArgumentException(const Instance& instance) {
  const Array& __args__ = Array::Handle(Array::New(1));
  __args__.SetAt(0, instance);
  Exceptions::ThrowByType(Exceptions::kArgument, __args__);
}

NativeFunction NativeEntry::ResolveNative(const Library& library,
                                          const String& function_name,
                                          int number_of_arguments,
                                          bool* auto_setup_scope) {
  // Now resolve the native function to the corresponding native entrypoint.
  if (library.native_entry_resolver() == NULL) {
    // Native methods are not allowed in the library to which this
    // class belongs in.
    return NULL;
  }
  Dart_NativeFunction native_function = NULL;
  {
    Thread* T = Thread::Current();
    TransitionVMToNative transition(T);
    Dart_EnterScope();  // Enter a new Dart API scope as we invoke API entries.
    Dart_NativeEntryResolver resolver = library.native_entry_resolver();
    native_function = resolver(Api::NewHandle(T, function_name.raw()),
                               number_of_arguments, auto_setup_scope);
    Dart_ExitScope();  // Exit the Dart API scope.
  }
  return reinterpret_cast<NativeFunction>(native_function);
}

const uint8_t* NativeEntry::ResolveSymbolInLibrary(const Library& library,
                                                   uword pc) {
  Dart_NativeEntrySymbol symbol_resolver =
      library.native_entry_symbol_resolver();
  if (symbol_resolver == NULL) {
    // Cannot reverse lookup native entries.
    return NULL;
  }
  return symbol_resolver(reinterpret_cast<Dart_NativeFunction>(pc));
}

const uint8_t* NativeEntry::ResolveSymbol(uword pc) {
  Thread* thread = Thread::Current();
  REUSABLE_GROWABLE_OBJECT_ARRAY_HANDLESCOPE(thread);
  GrowableObjectArray& libs = reused_growable_object_array_handle.Handle();
  libs ^= thread->isolate()->object_store()->libraries();
  ASSERT(!libs.IsNull());
  intptr_t num_libs = libs.Length();
  for (intptr_t i = 0; i < num_libs; i++) {
    REUSABLE_LIBRARY_HANDLESCOPE(thread);
    Library& lib = reused_library_handle.Handle();
    lib ^= libs.At(i);
    ASSERT(!lib.IsNull());
    const uint8_t* r = ResolveSymbolInLibrary(lib, pc);
    if (r != NULL) {
      return r;
    }
  }
  return NULL;
}

bool NativeEntry::ReturnValueIsError(NativeArguments* arguments) {
  RawObject* retval = arguments->ReturnValue();
  return (retval->IsHeapObject() &&
          RawObject::IsErrorClassId(retval->GetClassId()));
}

void NativeEntry::PropagateErrors(NativeArguments* arguments) {
  Thread* thread = arguments->thread();
  thread->UnwindScopes(thread->top_exit_frame_info());

  // The thread->zone() is different here than before we unwound.
  const Object& error =
      Object::Handle(thread->zone(), arguments->ReturnValue());
  Exceptions::PropagateError(Error::Cast(error));
  UNREACHABLE();
}

uword NativeEntry::NoScopeNativeCallWrapperEntry() {
  uword entry = reinterpret_cast<uword>(NativeEntry::NoScopeNativeCallWrapper);
#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
  // DBC does not use redirections unlike other simulators.
  entry = Simulator::RedirectExternalReference(
      entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments);
#endif
  return entry;
}

void NativeEntry::NoScopeNativeCallWrapper(Dart_NativeArguments args,
                                           Dart_NativeFunction func) {
  CHECK_STACK_ALIGNMENT;
  NoScopeNativeCallWrapperNoStackCheck(args, func);
}

void NativeEntry::NoScopeNativeCallWrapperNoStackCheck(
    Dart_NativeArguments args,
    Dart_NativeFunction func) {
  VERIFY_ON_TRANSITION;
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  /* Tell MemorySanitizer 'arguments' is initialized by generated code. */
  MSAN_UNPOISON(arguments, sizeof(*arguments));
  Thread* thread = arguments->thread();
  ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
  {
    TransitionGeneratedToNative transition(thread);
    func(args);
    if (ReturnValueIsError(arguments)) {
      PropagateErrors(arguments);
    }
  }
  ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
  VERIFY_ON_TRANSITION;
}

uword NativeEntry::AutoScopeNativeCallWrapperEntry() {
  uword entry =
      reinterpret_cast<uword>(NativeEntry::AutoScopeNativeCallWrapper);
#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
  // DBC does not use redirections unlike other simulators.
  entry = Simulator::RedirectExternalReference(
      entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments);
#endif
  return entry;
}

void NativeEntry::AutoScopeNativeCallWrapper(Dart_NativeArguments args,
                                             Dart_NativeFunction func) {
  CHECK_STACK_ALIGNMENT;
  AutoScopeNativeCallWrapperNoStackCheck(args, func);
}

void NativeEntry::AutoScopeNativeCallWrapperNoStackCheck(
    Dart_NativeArguments args,
    Dart_NativeFunction func) {
  VERIFY_ON_TRANSITION;
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  /* Tell MemorySanitizer 'arguments' is initialized by generated code. */
  MSAN_UNPOISON(arguments, sizeof(*arguments));
  Thread* thread = arguments->thread();
  ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
  {
    Isolate* isolate = thread->isolate();
    ApiState* state = isolate->api_state();
    ASSERT(state != NULL);
    ApiLocalScope* current_top_scope = thread->api_top_scope();
    ApiLocalScope* scope = thread->api_reusable_scope();
    TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func));
    TransitionGeneratedToNative transition(thread);
    if (scope == NULL) {
      scope =
          new ApiLocalScope(current_top_scope, thread->top_exit_frame_info());
      ASSERT(scope != NULL);
    } else {
      scope->Reinit(thread, current_top_scope, thread->top_exit_frame_info());
      thread->set_api_reusable_scope(NULL);
    }
    thread->set_api_top_scope(scope);  // New scope is now the top scope.

    func(args);
    if (ReturnValueIsError(arguments)) {
      PropagateErrors(arguments);
    }

    ASSERT(current_top_scope == scope->previous());
    thread->set_api_top_scope(current_top_scope);  // Reset top scope to prev.
    if (thread->api_reusable_scope() == NULL) {
      scope->Reset(thread);  // Reset the old scope which we just exited.
      thread->set_api_reusable_scope(scope);
    } else {
      ASSERT(thread->api_reusable_scope() != scope);
      delete scope;
    }
    DEOPTIMIZE_ALOT;
  }
  ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
  VERIFY_ON_TRANSITION;
}

// DBC does not support lazy native call linking.
#if !defined(TARGET_ARCH_DBC)
static NativeFunction ResolveNativeFunction(Zone* zone,
                                            const Function& func,
                                            bool* is_bootstrap_native,
                                            bool* is_auto_scope) {
  const Class& cls = Class::Handle(zone, func.Owner());
  const Library& library = Library::Handle(zone, cls.library());

  *is_bootstrap_native =
      Bootstrap::IsBootstapResolver(library.native_entry_resolver());

  const String& native_name = String::Handle(zone, func.native_name());
  ASSERT(!native_name.IsNull());

  const int num_params = NativeArguments::ParameterCountForResolution(func);
  NativeFunction native_function = NativeEntry::ResolveNative(
      library, native_name, num_params, is_auto_scope);
  if (native_function == NULL) {
    FATAL2("Failed to resolve native function '%s' in '%s'\n",
           native_name.ToCString(), func.ToQualifiedCString());
  }
  return native_function;
}

uword NativeEntry::LinkNativeCallEntry() {
  uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall);
#if defined(USING_SIMULATOR)
  entry = Simulator::RedirectExternalReference(
      entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
#endif
  return entry;
}

void NativeEntry::LinkNativeCall(Dart_NativeArguments args) {
  CHECK_STACK_ALIGNMENT;
  VERIFY_ON_TRANSITION;
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  /* Tell MemorySanitizer 'arguments' is initialized by generated code. */
  MSAN_UNPOISON(arguments, sizeof(*arguments));
  TRACE_NATIVE_CALL("%s", "LinkNative");

  NativeFunction target_function = NULL;
  bool is_bootstrap_native = false;
  bool is_auto_scope = true;

  {
    TransitionGeneratedToVM transition(arguments->thread());
    StackZone stack_zone(arguments->thread());
    Zone* zone = stack_zone.GetZone();

    DartFrameIterator iterator(arguments->thread(),
                               StackFrameIterator::kNoCrossThreadIteration);
    StackFrame* caller_frame = iterator.NextFrame();

    const Code& code = Code::Handle(zone, caller_frame->LookupDartCode());
    const Function& func = Function::Handle(zone, code.function());

    if (FLAG_trace_natives) {
      THR_Print("Resolving native target for %s\n", func.ToCString());
    }

    target_function =
        ResolveNativeFunction(arguments->thread()->zone(), func,
                              &is_bootstrap_native, &is_auto_scope);
    ASSERT(target_function != NULL);

#if defined(DEBUG)
    {
      NativeFunction current_function = NULL;
      const Code& current_trampoline =
          Code::Handle(zone, CodePatcher::GetNativeCallAt(
                                 caller_frame->pc(), code, &current_function));
#if !defined(USING_SIMULATOR)
      ASSERT(current_function ==
             reinterpret_cast<NativeFunction>(LinkNativeCall));
#else
      ASSERT(
          current_function ==
          reinterpret_cast<NativeFunction>(Simulator::RedirectExternalReference(
              reinterpret_cast<uword>(LinkNativeCall),
              Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments)));
#endif
      ASSERT(current_trampoline.raw() ==
             StubCode::CallBootstrapNative_entry()->code());
    }
#endif

    NativeFunction patch_target_function = target_function;
    Code& trampoline = Code::Handle(zone);
    if (is_bootstrap_native) {
      trampoline = StubCode::CallBootstrapNative_entry()->code();
#if defined(USING_SIMULATOR)
      patch_target_function =
          reinterpret_cast<NativeFunction>(Simulator::RedirectExternalReference(
              reinterpret_cast<uword>(patch_target_function),
              Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments));
#endif
    } else if (is_auto_scope) {
      trampoline = StubCode::CallAutoScopeNative_entry()->code();
    } else {
      trampoline = StubCode::CallNoScopeNative_entry()->code();
    }

    CodePatcher::PatchNativeCallAt(caller_frame->pc(), code,
                                   patch_target_function, trampoline);

    if (FLAG_trace_natives) {
      THR_Print("    -> %p (%s)\n", target_function,
                is_bootstrap_native ? "bootstrap" : "non-bootstrap");
    }
  }
  VERIFY_ON_TRANSITION;

  // Tail-call resolved target.
  if (is_bootstrap_native) {
    target_function(arguments);
  } else if (is_auto_scope) {
    // Because this call is within a compilation unit, Clang doesn't respect
    // the ABI alignment here.
    NativeEntry::AutoScopeNativeCallWrapperNoStackCheck(
        args, reinterpret_cast<Dart_NativeFunction>(target_function));
  } else {
    // Because this call is within a compilation unit, Clang doesn't respect
    // the ABI alignment here.
    NativeEntry::NoScopeNativeCallWrapperNoStackCheck(
        args, reinterpret_cast<Dart_NativeFunction>(target_function));
  }
}
#endif  // !defined(TARGET_ARCH_DBC)

}  // namespace dart
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: MQuery.hxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: ihi $ $Date: 2006-10-18 13:11:02 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    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
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_MAB_QUERY_HXX_
#define _CONNECTIVITY_MAB_QUERY_HXX_

#ifndef _CONNECTIVITY_MAB_COLUMNALIAS_HXX_
#include "MColumnAlias.hxx"
#endif
#ifndef CONNECITIVITY_MOZAB_ERROR_RESOURCE_HXX
#include "MErrorResource.hxx"
#endif
#include <connectivity/FValue.hxx>
#ifndef _CONNECTIVITY_MAB_NS_DECLARES_HXX_
#include "MNSDeclares.hxx"
#endif
#ifndef _THREAD_HXX_
#include <osl/thread.hxx>
#endif
#ifndef _COM_SUN_STAR_MOZILLA_MOZILLPRODUCTTYPE_HPP_
#include <com/sun/star/mozilla/MozillaProductType.hpp>
#endif

namespace connectivity
{
    namespace mozab
    {

        class  MQueryHelper;
        struct MQueryDirectory;

        namespace MQueryOp {
             typedef enum {
                 Exists         = 0,
                 DoesNotExist   = 1,
                 Contains       = 2,
                 DoesNotContain = 3,
                 Is             = 4,
                 IsNot          = 5,
                 BeginsWith     = 6,
                 EndsWith       = 7,
                 SoundsLike     = 8,
                 RegExp         = 9
            } cond_type;
        }

        class MQueryExpressionBase {
        public:
            typedef enum {
                Unknown,
                StringExpr,
                Expr
            } node_type;

        protected:
            node_type   m_eNodeType;

            MQueryExpressionBase() : m_eNodeType( Unknown ) {}
            MQueryExpressionBase( node_type _eNodeType ) : m_eNodeType( _eNodeType ) {}

        public:
            sal_Bool   isUnknown( ) { return m_eNodeType == Unknown; }
            sal_Bool   isStringExpr( ) { return m_eNodeType == StringExpr; }
            sal_Bool   isExpr( ) { return m_eNodeType == Expr; }
        };

        class MQueryExpressionString : public MQueryExpressionBase {
        protected:
            ::rtl::OUString     m_aName;         // LHS
            MQueryOp::cond_type m_aBooleanCondition;
            ::rtl::OUString     m_aValue;        // RHS

        public:

            MQueryExpressionString( ::rtl::OUString&    lhs,
                                    MQueryOp::cond_type cond,
                                    ::rtl::OUString     rhs )
                : MQueryExpressionBase( MQueryExpressionBase::StringExpr )
                , m_aName( lhs )
                , m_aBooleanCondition( cond )
                , m_aValue( rhs )
            {
            }

            MQueryExpressionString( ::rtl::OUString&    lhs,
                                    MQueryOp::cond_type cond )
                : MQueryExpressionBase( MQueryExpressionBase::StringExpr )
                , m_aName( lhs )
                , m_aBooleanCondition( cond )
                , m_aValue( ::rtl::OUString() )
            {
            }

            const ::rtl::OUString&    getName()  { return m_aName; }
            const MQueryOp::cond_type getCond()  { return m_aBooleanCondition; }
            const ::rtl::OUString&    getValue() { return m_aValue; }
        };

        class MQuery;

        class MQueryExpression : public MQueryExpressionBase
        {
            friend class MQuery;

        public:
            typedef ::std::vector< MQueryExpressionBase* > ExprVector;

            typedef enum {
                AND,
                OR
            } bool_cond;

            void setExpressions( ExprVector& _exprVector )
                            { m_aExprVector = _exprVector; }

            // All expressions on a peer level use same condition operator
            void setExpressionCondition( bool_cond _cond )
                            { m_aExprCondType = _cond; }

            ExprVector& getExpressions( )
                            { return m_aExprVector; }

            // All expressions on a peer level use same condition operator
            bool_cond getExpressionCondition( )
                            { return m_aExprCondType; }

            MQueryExpression() : MQueryExpressionBase( MQueryExpressionBase::Expr ),
                                 m_aExprCondType( OR )
                            { m_aExprVector.clear(); }

        protected:
            ExprVector          m_aExprVector;
            bool_cond           m_aExprCondType;

        };

        class MQuery : public ErrorResourceAccess
        {
            /*
             * A query resultset with a maximum limit of
             * m_nMaxNrOfReturns return items, is created from
             * the following SQL statement:
             *
             * -------------------------------------------------
             * SELECT m_aAttributes FROM m_aAddressbook
             * WHERE  m_aMatchItems SQL_OPR m_aMatchValue
             * -------------------------------------------------
             *
             * We are\are not, depending on boolean m_bQuerySubDirs,
             * interested in querying the sub-directories of the
             * addressbook directory, if any.
             *
             * SQL_OPR:
             * m_aSqlOppr contains the SQL operations for every
             * attribute in m_aAttributes.
             * This member must be initialised together with
             * m_aAttributes.
             *
             * The SQL operations defined for 'SQL_OPR' are:
             * matchExists         = 0,
             * matchDoesNotExist   = 1,
             * matchContains       = 2,
             * matchDoesNotContain = 3,
             * matchIs             = 4,
             * matchIsNot          = 5,
             * matchBeginsWith     = 6,
             * matchEndsWith       = 7,
             * matchSoundsLike     = 8,
             * matchRegExp         = 9.
             * There must be mapping to one of these values.
             *
             * The following members MUST be initialised before
             * a query is executed:
             * m_Attributes, m_aMapAttrOppr, m_aAddressbook,
             * m_aMatchItems and m_aMatchValue.
             *
             * m_bQuerySubDirs and m_nMaxNrReturns are set to a
             * default value in the constructor which can be
             * overridden. If (element of) m_aSqlOppr is not set,
             * the default SQL operation is 'matchIs'.
             *
             */
        private:
            MQueryDirectory                *m_aQueryDirectory;
            MQueryHelper                   *m_aQueryHelper;
            ::std::vector< ::rtl::OUString> m_aAttributes;
            ::rtl::OUString                 m_aAddressbook;
            sal_Int32                       m_nMaxNrOfReturns;
            sal_Bool                        m_bQuerySubDirs;
            MQueryExpression                m_aExpr;
            const OColumnAlias&             m_rColumnAlias;
            mutable sal_Bool                m_aErrorOccurred;
            ::com::sun::star::mozilla::MozillaProductType m_Product;
            ::rtl::OUString                               m_Profile;
            void construct();
        protected:
            ::osl::Mutex                    m_aMutex;
#if OSL_DEBUG_LEVEL > 0
            oslThreadIdentifier m_oThreadID;
#endif

        public:
            /*
             * - Contains accessors to the members of this class.
             * - executeQuery() initiates a non-blocking query.
             */
            sal_Int32                       executeQuery(OConnection* _pCon);
            sal_Int32                       executeQueryProxied(OConnection* _pCon); //Used only by MNSMozabProxy

            sal_Int32                       createNewCard(); //return Row count number
            sal_Int32                       deleteRow(const sal_Int32 rowIndex);
            sal_Int32                       commitRow(const sal_Int32 rowIndex);
            sal_Bool                        resyncRow(sal_Int32 nDBRow);

            sal_Bool                        isWritable(OConnection* _pCon);

            sal_uInt32                      InsertLoginInfo(OConnection* _pCon);

            void                            setAttributes( ::std::vector< ::rtl::OUString>&);
            const                           ::std::vector< ::rtl::OUString> &getAttributes(void) const;

            void                            setAddressbook( ::rtl::OUString&);
            ::rtl::OUString                 getAddressbook(void) const;

            const OColumnAlias&             getColumnAlias() const { return m_rColumnAlias; }

            void                            setExpression( MQueryExpression &_expr );

            void                            setMaxNrOfReturns( const sal_Int32);
            sal_Int32                       getMaxNrOfReturns(void) const;

            void                            setQuerySubDirs( sal_Bool&);
            sal_Bool                        getQuerySubDirs(void) const;

            sal_Int32                       getRowCount( void );
            sal_uInt32                      getRealRowCount( void );
            sal_Bool                        queryComplete( void );
            sal_Bool                        waitForQueryComplete( void );
            sal_Bool                        checkRowAvailable( sal_Int32 nDBRow );
            sal_Bool                        getRowValue( connectivity::ORowSetValue& rValue,
                                                         sal_Int32 nDBRow,
                                                         const rtl::OUString& aDBColumnName,
                                                         sal_Int32 nType ) const;
            sal_Bool                        setRowValue( connectivity::ORowSetValue& rValue,
                                                         sal_Int32 nDBRow,
                                                         const rtl::OUString& aDBColumnName,
                                                         sal_Int32 nType ) const;
            sal_Int32                       getRowStates(sal_Int32 nDBRow);
            sal_Bool                        setRowStates(sal_Int32 nDBRow,sal_Int32 aState);

            sal_Bool                        errorOccurred() const
                                            { return m_aErrorOccurred; };

        public:
//          MQuery();
            MQuery( const OColumnAlias& _ca );
            virtual ~MQuery();
            static MNameMapper* CreateNameMapper();
            static void FreeNameMapper( MNameMapper* _ptr );
        };
    }
}

#endif // _CONNECTIVITY_MAB_QUERY_HXX_

<commit_msg>INTEGRATION: CWS changefileheader (1.15.204); FILE MERGED 2008/04/01 15:09:01 thb 1.15.204.3: #i85898# Stripping all external header guards 2008/04/01 10:53:13 thb 1.15.204.2: #i85898# Stripping all external header guards 2008/03/28 15:23:59 rt 1.15.204.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: MQuery.hxx,v $
 * $Revision: 1.16 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_MAB_QUERY_HXX_
#define _CONNECTIVITY_MAB_QUERY_HXX_

#include "MColumnAlias.hxx"
#include "MErrorResource.hxx"
#include <connectivity/FValue.hxx>
#include "MNSDeclares.hxx"
#include <osl/thread.hxx>
#ifndef _COM_SUN_STAR_MOZILLA_MOZILLPRODUCTTYPE_HPP_
#include <com/sun/star/mozilla/MozillaProductType.hpp>
#endif

namespace connectivity
{
    namespace mozab
    {

        class  MQueryHelper;
        struct MQueryDirectory;

        namespace MQueryOp {
             typedef enum {
                 Exists         = 0,
                 DoesNotExist   = 1,
                 Contains       = 2,
                 DoesNotContain = 3,
                 Is             = 4,
                 IsNot          = 5,
                 BeginsWith     = 6,
                 EndsWith       = 7,
                 SoundsLike     = 8,
                 RegExp         = 9
            } cond_type;
        }

        class MQueryExpressionBase {
        public:
            typedef enum {
                Unknown,
                StringExpr,
                Expr
            } node_type;

        protected:
            node_type   m_eNodeType;

            MQueryExpressionBase() : m_eNodeType( Unknown ) {}
            MQueryExpressionBase( node_type _eNodeType ) : m_eNodeType( _eNodeType ) {}

        public:
            sal_Bool   isUnknown( ) { return m_eNodeType == Unknown; }
            sal_Bool   isStringExpr( ) { return m_eNodeType == StringExpr; }
            sal_Bool   isExpr( ) { return m_eNodeType == Expr; }
        };

        class MQueryExpressionString : public MQueryExpressionBase {
        protected:
            ::rtl::OUString     m_aName;         // LHS
            MQueryOp::cond_type m_aBooleanCondition;
            ::rtl::OUString     m_aValue;        // RHS

        public:

            MQueryExpressionString( ::rtl::OUString&    lhs,
                                    MQueryOp::cond_type cond,
                                    ::rtl::OUString     rhs )
                : MQueryExpressionBase( MQueryExpressionBase::StringExpr )
                , m_aName( lhs )
                , m_aBooleanCondition( cond )
                , m_aValue( rhs )
            {
            }

            MQueryExpressionString( ::rtl::OUString&    lhs,
                                    MQueryOp::cond_type cond )
                : MQueryExpressionBase( MQueryExpressionBase::StringExpr )
                , m_aName( lhs )
                , m_aBooleanCondition( cond )
                , m_aValue( ::rtl::OUString() )
            {
            }

            const ::rtl::OUString&    getName()  { return m_aName; }
            const MQueryOp::cond_type getCond()  { return m_aBooleanCondition; }
            const ::rtl::OUString&    getValue() { return m_aValue; }
        };

        class MQuery;

        class MQueryExpression : public MQueryExpressionBase
        {
            friend class MQuery;

        public:
            typedef ::std::vector< MQueryExpressionBase* > ExprVector;

            typedef enum {
                AND,
                OR
            } bool_cond;

            void setExpressions( ExprVector& _exprVector )
                            { m_aExprVector = _exprVector; }

            // All expressions on a peer level use same condition operator
            void setExpressionCondition( bool_cond _cond )
                            { m_aExprCondType = _cond; }

            ExprVector& getExpressions( )
                            { return m_aExprVector; }

            // All expressions on a peer level use same condition operator
            bool_cond getExpressionCondition( )
                            { return m_aExprCondType; }

            MQueryExpression() : MQueryExpressionBase( MQueryExpressionBase::Expr ),
                                 m_aExprCondType( OR )
                            { m_aExprVector.clear(); }

        protected:
            ExprVector          m_aExprVector;
            bool_cond           m_aExprCondType;

        };

        class MQuery : public ErrorResourceAccess
        {
            /*
             * A query resultset with a maximum limit of
             * m_nMaxNrOfReturns return items, is created from
             * the following SQL statement:
             *
             * -------------------------------------------------
             * SELECT m_aAttributes FROM m_aAddressbook
             * WHERE  m_aMatchItems SQL_OPR m_aMatchValue
             * -------------------------------------------------
             *
             * We are\are not, depending on boolean m_bQuerySubDirs,
             * interested in querying the sub-directories of the
             * addressbook directory, if any.
             *
             * SQL_OPR:
             * m_aSqlOppr contains the SQL operations for every
             * attribute in m_aAttributes.
             * This member must be initialised together with
             * m_aAttributes.
             *
             * The SQL operations defined for 'SQL_OPR' are:
             * matchExists         = 0,
             * matchDoesNotExist   = 1,
             * matchContains       = 2,
             * matchDoesNotContain = 3,
             * matchIs             = 4,
             * matchIsNot          = 5,
             * matchBeginsWith     = 6,
             * matchEndsWith       = 7,
             * matchSoundsLike     = 8,
             * matchRegExp         = 9.
             * There must be mapping to one of these values.
             *
             * The following members MUST be initialised before
             * a query is executed:
             * m_Attributes, m_aMapAttrOppr, m_aAddressbook,
             * m_aMatchItems and m_aMatchValue.
             *
             * m_bQuerySubDirs and m_nMaxNrReturns are set to a
             * default value in the constructor which can be
             * overridden. If (element of) m_aSqlOppr is not set,
             * the default SQL operation is 'matchIs'.
             *
             */
        private:
            MQueryDirectory                *m_aQueryDirectory;
            MQueryHelper                   *m_aQueryHelper;
            ::std::vector< ::rtl::OUString> m_aAttributes;
            ::rtl::OUString                 m_aAddressbook;
            sal_Int32                       m_nMaxNrOfReturns;
            sal_Bool                        m_bQuerySubDirs;
            MQueryExpression                m_aExpr;
            const OColumnAlias&             m_rColumnAlias;
            mutable sal_Bool                m_aErrorOccurred;
            ::com::sun::star::mozilla::MozillaProductType m_Product;
            ::rtl::OUString                               m_Profile;
            void construct();
        protected:
            ::osl::Mutex                    m_aMutex;
#if OSL_DEBUG_LEVEL > 0
            oslThreadIdentifier m_oThreadID;
#endif

        public:
            /*
             * - Contains accessors to the members of this class.
             * - executeQuery() initiates a non-blocking query.
             */
            sal_Int32                       executeQuery(OConnection* _pCon);
            sal_Int32                       executeQueryProxied(OConnection* _pCon); //Used only by MNSMozabProxy

            sal_Int32                       createNewCard(); //return Row count number
            sal_Int32                       deleteRow(const sal_Int32 rowIndex);
            sal_Int32                       commitRow(const sal_Int32 rowIndex);
            sal_Bool                        resyncRow(sal_Int32 nDBRow);

            sal_Bool                        isWritable(OConnection* _pCon);

            sal_uInt32                      InsertLoginInfo(OConnection* _pCon);

            void                            setAttributes( ::std::vector< ::rtl::OUString>&);
            const                           ::std::vector< ::rtl::OUString> &getAttributes(void) const;

            void                            setAddressbook( ::rtl::OUString&);
            ::rtl::OUString                 getAddressbook(void) const;

            const OColumnAlias&             getColumnAlias() const { return m_rColumnAlias; }

            void                            setExpression( MQueryExpression &_expr );

            void                            setMaxNrOfReturns( const sal_Int32);
            sal_Int32                       getMaxNrOfReturns(void) const;

            void                            setQuerySubDirs( sal_Bool&);
            sal_Bool                        getQuerySubDirs(void) const;

            sal_Int32                       getRowCount( void );
            sal_uInt32                      getRealRowCount( void );
            sal_Bool                        queryComplete( void );
            sal_Bool                        waitForQueryComplete( void );
            sal_Bool                        checkRowAvailable( sal_Int32 nDBRow );
            sal_Bool                        getRowValue( connectivity::ORowSetValue& rValue,
                                                         sal_Int32 nDBRow,
                                                         const rtl::OUString& aDBColumnName,
                                                         sal_Int32 nType ) const;
            sal_Bool                        setRowValue( connectivity::ORowSetValue& rValue,
                                                         sal_Int32 nDBRow,
                                                         const rtl::OUString& aDBColumnName,
                                                         sal_Int32 nType ) const;
            sal_Int32                       getRowStates(sal_Int32 nDBRow);
            sal_Bool                        setRowStates(sal_Int32 nDBRow,sal_Int32 aState);

            sal_Bool                        errorOccurred() const
                                            { return m_aErrorOccurred; };

        public:
//          MQuery();
            MQuery( const OColumnAlias& _ca );
            virtual ~MQuery();
            static MNameMapper* CreateNameMapper();
            static void FreeNameMapper( MNameMapper* _ptr );
        };
    }
}

#endif // _CONNECTIVITY_MAB_QUERY_HXX_

<|endoftext|>


<commit_before>//
// Created by padeler on 21/6/2017.
//

#include "OpenPoseWrapper.h"

#include <glog/logging.h>

#include <openpose/core/headers.hpp>
#include <openpose/core/scaleAndSizeExtractor.hpp>
#include <openpose/gui/headers.hpp>

#include <openpose/pose/headers.hpp>
#include <openpose/face/headers.hpp>
#include <openpose/hand/headers.hpp>

#include <openpose/utilities/headers.hpp>

#include <boost/throw_exception.hpp>

// Detector specific paramters are here:
//#include <openpose/hand/handParameters.hpp>
//#include <openpose/face/faceParameters.hpp>
//#include <openpose/pose/poseParameters.hpp>

struct OpenPoseWrapper::PrivateData
{
    PrivateData(const op::Point<int> &netInputSize, const op::Point<int> &netInputSizeFaceAndHands,
                const op::Point<int> &outputSize, const op::PoseModel &poseModel,
                const std::string &modelFolder, int numScales, float scaleGap, float blendAlpha,
                const std::vector<op::HeatMapType> &heatMapTypes, const op::ScaleMode &heatMapScale, int gpuId):
            poseExtractorCaffe{poseModel, modelFolder, gpuId, heatMapTypes, heatMapScale},
            poseRenderer{poseModel, nullptr, 0.05, true, blendAlpha},
            scaleAndSizeExtractor{netInputSize, outputSize, numScales, scaleGap},

            faceExtractor{netInputSizeFaceAndHands, netInputSizeFaceAndHands, modelFolder, gpuId, heatMapTypes, heatMapScale},
            faceRenderer{0.4},
            faceDetector(poseModel),

            handDetector(poseModel),
            handRenderer{0.2},
            handExtractor{netInputSizeFaceAndHands, netInputSizeFaceAndHands, modelFolder, gpuId, 1, 0.4, heatMapTypes, heatMapScale}

    {}

    op::CvMatToOpInput cvMatToOpInput;
    op::CvMatToOpOutput cvMatToOpOutput;
    op::PoseExtractorCaffe poseExtractorCaffe;

    op::PoseGpuRenderer poseRenderer;

    op::FaceExtractorCaffe faceExtractor;
    op::FaceDetector faceDetector;
    op::FaceGpuRenderer faceRenderer;

    op::HandExtractorCaffe handExtractor;
    op::HandDetector handDetector;
    op::HandGpuRenderer handRenderer;

    op::OpOutputToCvMat opOutputToCvMat;
    op::ScaleAndSizeExtractor scaleAndSizeExtractor;
};

OpenPoseWrapper::OpenPoseWrapper(const cv::Size &netPoseSize, const cv::Size &netFaceHandsSize, const cv::Size &outSize,
                                 const std::string &model, const std::string &modelFolder, const int logLevel,
                                 bool downloadHeatmaps, OpenPoseWrapper::ScaleMode scaleMode, bool withFace, bool withHands, int gpuId):withFace(withFace), withHands(withHands) {
//    google::InitGoogleLogging("OpenPose Wrapper");

    // Step 1 - Set logging level
    // - 0 will output all the logging messages
    // - 255 will output nothing

    op::check(0 <= logLevel && logLevel <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__);
    op::ConfigureLog::setPriorityThreshold((op::Priority)logLevel);

    // Step 2 - Init params
    op::Point<int> outputSize(outSize.width,outSize.height);
    op::Point<int> netInputSize(netPoseSize.width,netPoseSize.height);
    op::Point<int> netInputSizeFaceAndHands(netFaceHandsSize.width,netFaceHandsSize.height);

    op::PoseModel poseModel;

    op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
    if (model == "COCO")
        poseModel = op::PoseModel::COCO_18;
    else if (model == "MPI")
        poseModel = op::PoseModel::MPI_15;
    else if (model == "MPI_4_layers")
        poseModel = op::PoseModel::MPI_15_4;
    else
    {
        op::error("String does not correspond to any model (COCO, MPI, MPI_4_layers)", __LINE__, __FUNCTION__, __FILE__);
        poseModel = op::PoseModel::COCO_18;
    }

    int numScales = 1;
    float scaleGap = 0.3; // not used if numScales==1
    float blendAlpha = 0.6;

    //if you need to download bodypart heatmaps, Background or PAFs. They must be enabled here.
    std::vector<op::HeatMapType> hmt = {};
    if(downloadHeatmaps)
    {
        hmt = {op::HeatMapType::Parts, op::HeatMapType::Background, op::HeatMapType::PAFs};
    }

    // Step 3 - Initialize all required classes
    membersPtr = std::shared_ptr<PrivateData>(new PrivateData(netInputSize, netInputSizeFaceAndHands,
                                                              outputSize, poseModel, modelFolder,
                                                              numScales, scaleGap, blendAlpha,
                                                              hmt, (op::ScaleMode)scaleMode, gpuId));

    // Step 4 - Initialize resources on desired thread (in this case single thread, i.e. we init resources here)
    membersPtr->poseExtractorCaffe.initializationOnThread();
    membersPtr->poseRenderer.initializationOnThread();
    if(withFace) {
        membersPtr->faceExtractor.initializationOnThread();
        membersPtr->faceRenderer.initializationOnThread();
    }
    if(withHands) {
        membersPtr->handExtractor.initializationOnThread();
        membersPtr->handRenderer.initializationOnThread();
    }
}

void OpenPoseWrapper::detectPose(const cv::Mat &rgb) {
    // Step 2 - Format input image to OpenPose input and output formats

    const op::Point<int> imageSize{rgb.cols, rgb.rows};
    std::vector<double> scaleInputToNetInputs;
    std::vector<op::Point<int>> netInputSizes;
    double scaleInputToOutput;
    op::Point<int> outputResolution;
    std::tie(scaleInputToNetInputs, netInputSizes, scaleInputToOutput, outputResolution)
            = membersPtr->scaleAndSizeExtractor.extract(imageSize);
    op::Array<float> netInputArray = membersPtr->cvMatToOpInput.createArray(rgb, scaleInputToNetInputs, netInputSizes);

    // Step 3 - Estimate poseKeypoints
    membersPtr->poseExtractorCaffe.forwardPass(netInputArray, imageSize, scaleInputToNetInputs);
}

void OpenPoseWrapper::detectFace(const cv::Mat &rgb) {
    if(!withFace)
    {
        BOOST_THROW_EXCEPTION(std::runtime_error("Face network was not initialized."));
    }
    const auto poseKeypoints = membersPtr->poseExtractorCaffe.getPoseKeypoints();
    const auto faceRectsOP = membersPtr->faceDetector.detectFaces(poseKeypoints, 1.0f);

    this->faceRects = cv::Mat(faceRectsOP.size(), 4, CV_32SC1, cv::Scalar(0));
    cv::Mat fr = this->faceRects.reshape(4,faceRects.rows); // stupid cv::Mat iterator cannot iterate over rows.
    std::transform(faceRectsOP.begin(), faceRectsOP.end(), fr.begin<cv::Vec4i>(), [](const op::Rectangle<float> &r) -> cv::Vec4i { return cv::Vec4i(r.x, r.y, r.width, r.height);});

    membersPtr->faceExtractor.forwardPass(faceRectsOP, rgb, 1.0f);
}

void OpenPoseWrapper::detectFace(const cv::Mat &rgb, const cv::Mat &faceRects)
{
    if(!withFace)
    {
        BOOST_THROW_EXCEPTION(std::runtime_error("Face network was not initialized."));
    }
    if(faceRects.cols!=4 or faceRects.type()!=CV_32SC1)
    {
        BOOST_THROW_EXCEPTION(std::runtime_error("Invalid face rectangles format. Expected Nx4 mat with type CV_32SC1"));
    }

    this->faceRects = faceRects; // keep a copy
    std::vector<op::Rectangle<float> > faceRectsOP(faceRects.rows);
    cv::Mat fr = faceRects.reshape(4,faceRects.rows); // stupid cv::Mat iterator cannot iterate over rows.
    std::transform(fr.begin<cv::Vec4i>(), fr.end<cv::Vec4i>(), faceRectsOP.begin(),
                   [](const cv::Vec4i &r) -> op::Rectangle<float> { return op::Rectangle<float>(r[0], r[1], r[2], r[3]);});

    membersPtr->faceExtractor.forwardPass(faceRectsOP, rgb, 1.0f);
}

void OpenPoseWrapper::detectHands(const cv::Mat &rgb) {
    if(!withHands)
    {
        BOOST_THROW_EXCEPTION(std::runtime_error("Hand network was not initialized."));
    }

    const auto poseKeypoints = membersPtr->poseExtractorCaffe.getPoseKeypoints();
    const auto handRectsOP = membersPtr->handDetector.detectHands(poseKeypoints, 1.0f);

    this->handRects= cv::Mat(handRectsOP.size(), 8, CV_32SC1, cv::Scalar(0));
    cv::Mat hr = this->handRects.reshape(8,handRects.rows); // stupid cv::Mat iterator cannot iterate over rows.
    std::transform(handRectsOP.begin(), handRectsOP.end(), hr.begin<cv::Vec8i>(),
                   [](const std::array<op::Rectangle<float>, 2> &r) -> cv::Vec8i
                   { return cv::Vec8i(r[0].x, r[0].y, r[0].width, r[0].height, r[1].x, r[1].y, r[1].width, r[1].height); });

    membersPtr->handExtractor.forwardPass(handRectsOP, rgb, 1.0f);
}

void OpenPoseWrapper::detectHands(const cv::Mat &rgb, const cv::Mat &handRects)
{
    if(!withHands)
    {
        BOOST_THROW_EXCEPTION(std::runtime_error("Hand network was not initialized."));
    }
    if(handRects.cols!=8 or handRects.type()!=CV_32SC1)
    {
        BOOST_THROW_EXCEPTION(std::runtime_error("Invalid hand rectangles format. Expected Nx8 mat with type CV_32SC1"));
    }

    this->handRects = handRects;
    std::vector<std::array<op::Rectangle<float>, 2> > handRectsOP(handRects.rows);
    cv::Mat hr = handRects.reshape(8,handRects.rows); // stupid cv::Mat iterator cannot iterate over rows.
    std::transform(hr.begin<cv::Vec8i>(), hr.end<cv::Vec8i>(), handRectsOP.begin(),
                   [](const cv::Vec8i &r) -> std::array<op::Rectangle<float>, 2>
                   { return std::array<op::Rectangle<float>, 2>{op::Rectangle<float>(r[0], r[1], r[2], r[3]), op::Rectangle<float>(r[4], r[5], r[6], r[7])};});

    membersPtr->handExtractor.forwardPass(handRectsOP, rgb, 1.0f);
}

cv::Mat OpenPoseWrapper::render(const cv::Mat &rgb)
{
    op::Array<float> outputArray;

    const op::Point<int> imageSize{rgb.cols, rgb.rows};
    std::vector<double> scaleInputToNetInputs;
    std::vector<op::Point<int>> netInputSizes;
    double scaleInputToOutput;
    op::Point<int> outputResolution;
    std::tie(scaleInputToNetInputs, netInputSizes, scaleInputToOutput, outputResolution)
            = membersPtr->scaleAndSizeExtractor.extract(imageSize);

    outputArray = membersPtr->cvMatToOpOutput.createArray(rgb, scaleInputToOutput, outputResolution);

    const auto poseKeypoints = membersPtr->poseExtractorCaffe.getPoseKeypoints();
    membersPtr->poseRenderer.renderPose(outputArray, poseKeypoints, scaleInputToOutput);

    if(withFace){
        const auto faceKeypoints = membersPtr->faceExtractor.getFaceKeypoints();
        membersPtr->faceRenderer.renderFace(outputArray, faceKeypoints);
    }
    if(withHands) {
        const auto handKeypoints = membersPtr->handExtractor.getHandKeypoints();
        membersPtr->handRenderer.renderHand(outputArray, handKeypoints);
    }

    auto outputImage = membersPtr->opOutputToCvMat.formatToCvMat(outputArray);
    return outputImage;
}

OpenPoseWrapper::KeypointGroups OpenPoseWrapper::getKeypoints(KeypointType kpt) {

    op::Array<float> faces,persons;
    std::array<op::Array<float>, 2> hands;

    KeypointGroups res;
    switch(kpt){
        case FACE:
            faces = membersPtr->faceExtractor.getFaceKeypoints();
            res.push_back(faces.getConstCvMat()); // all faces in a cv::Mat at index 0
            break;
        case HAND:
            hands = membersPtr->handExtractor.getHandKeypoints();
            res.push_back(hands[0].getConstCvMat()); // left hands cv::Mat
            res.push_back(hands[1].getConstCvMat()); // right hands cv::Mat
            break;
        default: // POSE
            persons = membersPtr->poseExtractorCaffe.getPoseKeypoints();
            res.push_back(persons.getConstCvMat()); // all persons in a cv::Mat at index 0
            break;
    }

    return res;
}

cv::Mat OpenPoseWrapper::getHeatmaps() {
    op::Array<float> maps = membersPtr->poseExtractorCaffe.getHeatMaps();
    return maps.getConstCvMat().clone();
}

std::vector<cv::Mat> OpenPoseWrapper::getHandHeatmaps() {

    std::array<op::Array<float>, 2> maps = membersPtr->handExtractor.getHeatMaps();

    std::vector<cv::Mat> res;
    res.push_back(maps.at(0).getConstCvMat().clone());
    res.push_back(maps.at(1).getConstCvMat().clone());
    return res;
}

cv::Mat OpenPoseWrapper::getFaceHeatmaps() {
    op::Array<float> maps = membersPtr->faceExtractor.getHeatMaps();
    return maps.getConstCvMat().clone();
}
<commit_msg>Openpose API fix, now up-to-date with commit e086e6f<commit_after>//
// Created by padeler on 21/6/2017.
//

#include "OpenPoseWrapper.h"

#include <glog/logging.h>

#include <openpose/core/headers.hpp>
#include <openpose/core/scaleAndSizeExtractor.hpp>
#include <openpose/gui/headers.hpp>

#include <openpose/pose/headers.hpp>
#include <openpose/face/headers.hpp>
#include <openpose/hand/headers.hpp>

#include <openpose/utilities/headers.hpp>

#include <boost/throw_exception.hpp>

// Detector specific paramters are here:
//#include <openpose/hand/handParameters.hpp>
//#include <openpose/face/faceParameters.hpp>
//#include <openpose/pose/poseParameters.hpp>

struct OpenPoseWrapper::PrivateData
{
    PrivateData(const op::Point<int> &netInputSize, const op::Point<int> &netInputSizeFaceAndHands,
                const op::Point<int> &outputSize, const op::PoseModel &poseModel,
                const std::string &modelFolder, int numScales, float scaleGap, float blendAlpha,
                const std::vector<op::HeatMapType> &heatMapTypes, const op::ScaleMode &heatMapScale, int gpuId):
            poseExtractorCaffe{poseModel, modelFolder, gpuId, heatMapTypes, heatMapScale},
            poseRenderer{poseModel, nullptr, 0.05, true, blendAlpha},
            scaleAndSizeExtractor{netInputSize, outputSize, numScales, scaleGap},

            faceExtractor{netInputSizeFaceAndHands, netInputSizeFaceAndHands, modelFolder, gpuId, heatMapTypes, heatMapScale},
            faceRenderer{0.4},
            faceDetector(poseModel),

            handDetector(poseModel),
            handRenderer{0.2},
            handExtractor{netInputSizeFaceAndHands, netInputSizeFaceAndHands, modelFolder, gpuId, 1, 0.4, heatMapTypes, heatMapScale}

    {}

    op::CvMatToOpInput cvMatToOpInput;
    op::CvMatToOpOutput cvMatToOpOutput;
    op::PoseExtractorCaffe poseExtractorCaffe;

    op::PoseGpuRenderer poseRenderer;

    op::FaceExtractorCaffe faceExtractor;
    op::FaceDetector faceDetector;
    op::FaceGpuRenderer faceRenderer;

    op::HandExtractorCaffe handExtractor;
    op::HandDetector handDetector;
    op::HandGpuRenderer handRenderer;

    op::OpOutputToCvMat opOutputToCvMat;
    op::ScaleAndSizeExtractor scaleAndSizeExtractor;
};

OpenPoseWrapper::OpenPoseWrapper(const cv::Size &netPoseSize, const cv::Size &netFaceHandsSize, const cv::Size &outSize,
                                 const std::string &model, const std::string &modelFolder, const int logLevel,
                                 bool downloadHeatmaps, OpenPoseWrapper::ScaleMode scaleMode, bool withFace, bool withHands, int gpuId):withFace(withFace), withHands(withHands) {
//    google::InitGoogleLogging("OpenPose Wrapper");

    // Step 1 - Set logging level
    // - 0 will output all the logging messages
    // - 255 will output nothing

    op::check(0 <= logLevel && logLevel <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__);
    op::ConfigureLog::setPriorityThreshold((op::Priority)logLevel);

    // Step 2 - Init params
    op::Point<int> outputSize(outSize.width,outSize.height);
    op::Point<int> netInputSize(netPoseSize.width,netPoseSize.height);
    op::Point<int> netInputSizeFaceAndHands(netFaceHandsSize.width,netFaceHandsSize.height);

    op::PoseModel poseModel;

    op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
    if (model == "COCO")
        poseModel = op::PoseModel::COCO_18;
    else if (model == "MPI")
        poseModel = op::PoseModel::MPI_15;
    else if (model == "MPI_4_layers")
        poseModel = op::PoseModel::MPI_15_4;
    else
    {
        op::error("String does not correspond to any model (COCO, MPI, MPI_4_layers)", __LINE__, __FUNCTION__, __FILE__);
        poseModel = op::PoseModel::COCO_18;
    }

    int numScales = 1;
    float scaleGap = 0.3; // not used if numScales==1
    float blendAlpha = 0.6;

    //if you need to download bodypart heatmaps, Background or PAFs. They must be enabled here.
    std::vector<op::HeatMapType> hmt = {};
    if(downloadHeatmaps)
    {
        hmt = {op::HeatMapType::Parts, op::HeatMapType::Background, op::HeatMapType::PAFs};
    }

    // Step 3 - Initialize all required classes
    membersPtr = std::shared_ptr<PrivateData>(new PrivateData(netInputSize, netInputSizeFaceAndHands,
                                                              outputSize, poseModel, modelFolder,
                                                              numScales, scaleGap, blendAlpha,
                                                              hmt, (op::ScaleMode)scaleMode, gpuId));

    // Step 4 - Initialize resources on desired thread (in this case single thread, i.e. we init resources here)
    membersPtr->poseExtractorCaffe.initializationOnThread();
    membersPtr->poseRenderer.initializationOnThread();
    if(withFace) {
        membersPtr->faceExtractor.initializationOnThread();
        membersPtr->faceRenderer.initializationOnThread();
    }
    if(withHands) {
        membersPtr->handExtractor.initializationOnThread();
        membersPtr->handRenderer.initializationOnThread();
    }
}

void OpenPoseWrapper::detectPose(const cv::Mat &rgb) {
    // Step 2 - Format input image to OpenPose input and output formats

    const op::Point<int> imageSize{rgb.cols, rgb.rows};
    std::vector<double> scaleInputToNetInputs;
    std::vector<op::Point<int>> netInputSizes;
    double scaleInputToOutput;
    op::Point<int> outputResolution;
    std::tie(scaleInputToNetInputs, netInputSizes, scaleInputToOutput, outputResolution)
            = membersPtr->scaleAndSizeExtractor.extract(imageSize);
    std::vector<op::Array<float>> netInputArray = membersPtr->cvMatToOpInput.createArray(rgb, scaleInputToNetInputs, netInputSizes);

    // Step 3 - Estimate poseKeypoints
    membersPtr->poseExtractorCaffe.forwardPass(netInputArray, imageSize, scaleInputToNetInputs);
}

void OpenPoseWrapper::detectFace(const cv::Mat &rgb) {
    if(!withFace)
    {
        BOOST_THROW_EXCEPTION(std::runtime_error("Face network was not initialized."));
    }
    const auto poseKeypoints = membersPtr->poseExtractorCaffe.getPoseKeypoints();
    const auto faceRectsOP = membersPtr->faceDetector.detectFaces(poseKeypoints, 1.0f);

    this->faceRects = cv::Mat(faceRectsOP.size(), 4, CV_32SC1, cv::Scalar(0));
    cv::Mat fr = this->faceRects.reshape(4,faceRects.rows); // stupid cv::Mat iterator cannot iterate over rows.
    std::transform(faceRectsOP.begin(), faceRectsOP.end(), fr.begin<cv::Vec4i>(), [](const op::Rectangle<float> &r) -> cv::Vec4i { return cv::Vec4i(r.x, r.y, r.width, r.height);});

    membersPtr->faceExtractor.forwardPass(faceRectsOP, rgb, 1.0f);
}

void OpenPoseWrapper::detectFace(const cv::Mat &rgb, const cv::Mat &faceRects)
{
    if(!withFace)
    {
        BOOST_THROW_EXCEPTION(std::runtime_error("Face network was not initialized."));
    }
    if(faceRects.cols!=4 or faceRects.type()!=CV_32SC1)
    {
        BOOST_THROW_EXCEPTION(std::runtime_error("Invalid face rectangles format. Expected Nx4 mat with type CV_32SC1"));
    }

    this->faceRects = faceRects; // keep a copy
    std::vector<op::Rectangle<float> > faceRectsOP(faceRects.rows);
    cv::Mat fr = faceRects.reshape(4,faceRects.rows); // stupid cv::Mat iterator cannot iterate over rows.
    std::transform(fr.begin<cv::Vec4i>(), fr.end<cv::Vec4i>(), faceRectsOP.begin(),
                   [](const cv::Vec4i &r) -> op::Rectangle<float> { return op::Rectangle<float>(r[0], r[1], r[2], r[3]);});

    membersPtr->faceExtractor.forwardPass(faceRectsOP, rgb, 1.0f);
}

void OpenPoseWrapper::detectHands(const cv::Mat &rgb) {
    if(!withHands)
    {
        BOOST_THROW_EXCEPTION(std::runtime_error("Hand network was not initialized."));
    }

    const auto poseKeypoints = membersPtr->poseExtractorCaffe.getPoseKeypoints();
    const auto handRectsOP = membersPtr->handDetector.detectHands(poseKeypoints, 1.0f);

    this->handRects= cv::Mat(handRectsOP.size(), 8, CV_32SC1, cv::Scalar(0));
    cv::Mat hr = this->handRects.reshape(8,handRects.rows); // stupid cv::Mat iterator cannot iterate over rows.
    std::transform(handRectsOP.begin(), handRectsOP.end(), hr.begin<cv::Vec8i>(),
                   [](const std::array<op::Rectangle<float>, 2> &r) -> cv::Vec8i
                   { return cv::Vec8i(r[0].x, r[0].y, r[0].width, r[0].height, r[1].x, r[1].y, r[1].width, r[1].height); });

    membersPtr->handExtractor.forwardPass(handRectsOP, rgb, 1.0f);
}

void OpenPoseWrapper::detectHands(const cv::Mat &rgb, const cv::Mat &handRects)
{
    if(!withHands)
    {
        BOOST_THROW_EXCEPTION(std::runtime_error("Hand network was not initialized."));
    }
    if(handRects.cols!=8 or handRects.type()!=CV_32SC1)
    {
        BOOST_THROW_EXCEPTION(std::runtime_error("Invalid hand rectangles format. Expected Nx8 mat with type CV_32SC1"));
    }

    this->handRects = handRects;
    std::vector<std::array<op::Rectangle<float>, 2> > handRectsOP(handRects.rows);
    cv::Mat hr = handRects.reshape(8,handRects.rows); // stupid cv::Mat iterator cannot iterate over rows.
    std::transform(hr.begin<cv::Vec8i>(), hr.end<cv::Vec8i>(), handRectsOP.begin(),
                   [](const cv::Vec8i &r) -> std::array<op::Rectangle<float>, 2>
                   { return std::array<op::Rectangle<float>, 2>{op::Rectangle<float>(r[0], r[1], r[2], r[3]), op::Rectangle<float>(r[4], r[5], r[6], r[7])};});

    membersPtr->handExtractor.forwardPass(handRectsOP, rgb, 1.0f);
}

cv::Mat OpenPoseWrapper::render(const cv::Mat &rgb)
{
    op::Array<float> outputArray;

    const op::Point<int> imageSize{rgb.cols, rgb.rows};
    std::vector<double> scaleInputToNetInputs;
    std::vector<op::Point<int>> netInputSizes;
    double scaleInputToOutput;
    op::Point<int> outputResolution;
    std::tie(scaleInputToNetInputs, netInputSizes, scaleInputToOutput, outputResolution)
            = membersPtr->scaleAndSizeExtractor.extract(imageSize);

    outputArray = membersPtr->cvMatToOpOutput.createArray(rgb, scaleInputToOutput, outputResolution);

    const auto poseKeypoints = membersPtr->poseExtractorCaffe.getPoseKeypoints();
    membersPtr->poseRenderer.renderPose(outputArray, poseKeypoints, scaleInputToOutput);

    if(withFace){
        const auto faceKeypoints = membersPtr->faceExtractor.getFaceKeypoints();
        membersPtr->faceRenderer.renderFace(outputArray, faceKeypoints);
    }
    if(withHands) {
        const auto handKeypoints = membersPtr->handExtractor.getHandKeypoints();
        membersPtr->handRenderer.renderHand(outputArray, handKeypoints);
    }

    auto outputImage = membersPtr->opOutputToCvMat.formatToCvMat(outputArray);
    return outputImage;
}

OpenPoseWrapper::KeypointGroups OpenPoseWrapper::getKeypoints(KeypointType kpt) {

    op::Array<float> faces,persons;
    std::array<op::Array<float>, 2> hands;

    KeypointGroups res;
    switch(kpt){
        case FACE:
            faces = membersPtr->faceExtractor.getFaceKeypoints();
            res.push_back(faces.getConstCvMat()); // all faces in a cv::Mat at index 0
            break;
        case HAND:
            hands = membersPtr->handExtractor.getHandKeypoints();
            res.push_back(hands[0].getConstCvMat()); // left hands cv::Mat
            res.push_back(hands[1].getConstCvMat()); // right hands cv::Mat
            break;
        default: // POSE
            persons = membersPtr->poseExtractorCaffe.getPoseKeypoints();
            res.push_back(persons.getConstCvMat()); // all persons in a cv::Mat at index 0
            break;
    }

    return res;
}

cv::Mat OpenPoseWrapper::getHeatmaps() {
    op::Array<float> maps = membersPtr->poseExtractorCaffe.getHeatMaps();
    return maps.getConstCvMat().clone();
}

std::vector<cv::Mat> OpenPoseWrapper::getHandHeatmaps() {

    std::array<op::Array<float>, 2> maps = membersPtr->handExtractor.getHeatMaps();

    std::vector<cv::Mat> res;
    res.push_back(maps.at(0).getConstCvMat().clone());
    res.push_back(maps.at(1).getConstCvMat().clone());
    return res;
}

cv::Mat OpenPoseWrapper::getFaceHeatmaps() {
    op::Array<float> maps = membersPtr->faceExtractor.getHeatMaps();
    return maps.getConstCvMat().clone();
}
<|endoftext|>