<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: browserview.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 13:13:40 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"

#ifndef _EXTENSIONS_PROPCTRLR_BROWSERVIEW_HXX_
#include "browserview.hxx"
#endif
#ifndef _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_
#include "propertyeditor.hxx"
#endif
#ifndef _EXTENSIONS_FORMCTRLR_FORMHELPID_HRC_
#include "formhelpid.hrc"
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#include <memory>

//............................................................................
namespace pcr
{
//............................................................................

    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::lang;

    //========================================================================
    //= class OPropertyBrowserView
    //========================================================================
    DBG_NAME(OPropertyBrowserView)
    //------------------------------------------------------------------------
    OPropertyBrowserView::OPropertyBrowserView( const Reference< XMultiServiceFactory >& _rxORB,
                                 Window* _pParent, WinBits nBits)
                  :Window(_pParent, nBits | WB_3DLOOK)
                  ,m_xORB(_rxORB)
                  ,m_nActivePage(0)
    {
        DBG_CTOR(OPropertyBrowserView,NULL);

        m_pPropBox = new OPropertyEditor( this );
        m_pPropBox->SetHelpId(HID_FM_PROPDLG_TABCTR);
        m_pPropBox->setPageActivationHandler(LINK(this, OPropertyBrowserView, OnPageActivation));

        m_pPropBox->Show();
    }

    //------------------------------------------------------------------------
    IMPL_LINK(OPropertyBrowserView, OnPageActivation, void*, EMPTYARG)
    {
        m_nActivePage = m_pPropBox->GetCurPage();
        if (m_aPageActivationHandler.IsSet())
            m_aPageActivationHandler.Call(NULL);
        return 0L;
    }

    //------------------------------------------------------------------------
    OPropertyBrowserView::~OPropertyBrowserView()
    {
        if(m_pPropBox)
        {
            sal_uInt16 nTmpPage = m_pPropBox->GetCurPage();
            if (nTmpPage)
                m_nActivePage = nTmpPage;
            ::std::auto_ptr<Window> aTemp(m_pPropBox);
            m_pPropBox = NULL;
        }
        m_xORB = NULL;

        DBG_DTOR(OPropertyBrowserView, NULL);
    }

    //------------------------------------------------------------------------
    void OPropertyBrowserView::activatePage(sal_uInt16 _nPage)
    {
        m_nActivePage = _nPage;
        getPropertyBox()->SetPage(m_nActivePage);
    }

    //------------------------------------------------------------------------
    void OPropertyBrowserView::GetFocus()
    {
        if (m_pPropBox)
            m_pPropBox->GrabFocus();
        else
            Window::GetFocus();
    }

    //------------------------------------------------------------------------
    void OPropertyBrowserView::Resize()
    {
        Size aSize = GetOutputSizePixel();
        m_pPropBox->SetSizePixel(aSize);
    }

    // #95343# ---------------------------------------------------------------
    ::com::sun::star::awt::Size OPropertyBrowserView::getMinimumSize()
    {
        Size aSize = GetOutputSizePixel();
        aSize.setHeight( 250 );
        if( m_pPropBox )
            aSize.setWidth( m_pPropBox->getMinimumWidth() );
        return ::com::sun::star::awt::Size( aSize.Width(), aSize.Height() );
    }

//............................................................................
} // namespace pcr
//............................................................................

<commit_msg>INTEGRATION: CWS oihelp (1.12.42); FILE MERGED 2006/11/15 10:03:11 fs 1.12.42.2: #i71485# 2006/11/14 12:29:34 fs 1.12.42.1: #i71485# introduce a HelpSection (still fixed size, not finished completely)<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: browserview.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-13 11:56:36 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"

#ifndef _EXTENSIONS_PROPCTRLR_BROWSERVIEW_HXX_
#include "browserview.hxx"
#endif
#ifndef _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_
#include "propertyeditor.hxx"
#endif
#ifndef _EXTENSIONS_FORMCTRLR_FORMHELPID_HRC_
#include "formhelpid.hrc"
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#include <memory>

//............................................................................
namespace pcr
{
//............................................................................

    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::lang;

    //========================================================================
    //= class OPropertyBrowserView
    //========================================================================
    DBG_NAME(OPropertyBrowserView)
    //------------------------------------------------------------------------
    OPropertyBrowserView::OPropertyBrowserView( const Reference< XMultiServiceFactory >& _rxORB,
                                 Window* _pParent, WinBits nBits)
                  :Window(_pParent, nBits | WB_3DLOOK)
                  ,m_xORB(_rxORB)
                  ,m_nActivePage(0)
    {
        DBG_CTOR(OPropertyBrowserView,NULL);

        m_pPropBox = new OPropertyEditor( this );
        m_pPropBox->SetHelpId(HID_FM_PROPDLG_TABCTR);
        m_pPropBox->setPageActivationHandler(LINK(this, OPropertyBrowserView, OnPageActivation));

        m_pPropBox->Show();
    }

    //------------------------------------------------------------------------
    IMPL_LINK(OPropertyBrowserView, OnPageActivation, void*, EMPTYARG)
    {
        m_nActivePage = m_pPropBox->GetCurPage();
        if (m_aPageActivationHandler.IsSet())
            m_aPageActivationHandler.Call(NULL);
        return 0L;
    }

    //------------------------------------------------------------------------
    OPropertyBrowserView::~OPropertyBrowserView()
    {
        if(m_pPropBox)
        {
            sal_uInt16 nTmpPage = m_pPropBox->GetCurPage();
            if (nTmpPage)
                m_nActivePage = nTmpPage;
            ::std::auto_ptr<Window> aTemp(m_pPropBox);
            m_pPropBox = NULL;
        }
        m_xORB = NULL;

        DBG_DTOR(OPropertyBrowserView, NULL);
    }

    //------------------------------------------------------------------------
    void OPropertyBrowserView::activatePage(sal_uInt16 _nPage)
    {
        m_nActivePage = _nPage;
        getPropertyBox().SetPage(m_nActivePage);
    }

    //------------------------------------------------------------------------
    void OPropertyBrowserView::GetFocus()
    {
        if (m_pPropBox)
            m_pPropBox->GrabFocus();
        else
            Window::GetFocus();
    }

    //------------------------------------------------------------------------
    void OPropertyBrowserView::Resize()
    {
        Size aSize = GetOutputSizePixel();
        m_pPropBox->SetSizePixel(aSize);
    }

    // #95343# ---------------------------------------------------------------
    ::com::sun::star::awt::Size OPropertyBrowserView::getMinimumSize()
    {
        Size aSize = GetOutputSizePixel();
        if( m_pPropBox )
        {
            aSize.setHeight( m_pPropBox->getMinimumHeight() );
            aSize.setWidth( m_pPropBox->getMinimumWidth() );
        }
        return ::com::sun::star::awt::Size( aSize.Width(), aSize.Height() );
    }

//............................................................................
} // namespace pcr
//............................................................................

<|endoftext|>


<commit_before>#include "styleMixer.h"
#include "style/style.h"
#include "util/topologicalSort.h"
#include "yaml-cpp/yaml.h"

#include <algorithm>
#include <set>

namespace Tangram {

std::vector<std::string> StyleMixer::getStylesToMix(const Node& _style) {

    std::vector<std::string> names;

    // 'base' style is the first item to mix.
    if (const Node& base = _style["base"]) {
        if (base.IsScalar()) { names.push_back(base.Scalar()); }
    }

    // 'mix' styles are mixed next, in order of declaration.
    if (const Node& mix = _style["mix"]) {
        if (mix.IsScalar()) {
            names.push_back(mix.Scalar());
        } else if (mix.IsSequence()) {
            for (const auto& m : mix) {
                if (m.IsScalar()) { names.push_back(m.Scalar()); }
            }
        }
    }

    return names;
}

std::vector<std::string> StyleMixer::getMixingOrder(const Node& _styles) {

    // Input must be a map of names to style configuration nodes.
    if (!_styles.IsMap()) {
        return {};
    }

    // Dependencies are pairs of strings that form a DAG.
    // If style 'a' mixes style 'b', the dependency would be {'b', 'a'}.
    std::vector<std::pair<std::string, std::string>> dependencies;

    for (const auto& entry : _styles) {
        const auto& name = entry.first;
        const auto& config = entry.second;
        for (const auto& mix : getStylesToMix(config)) {
            dependencies.push_back({ mix, name.Scalar() });
        }
    }

    return topologicalSort(dependencies);
}

void StyleMixer::mixStyleNodes(Node _styles) {

    // First determine the order of nodes to evaluate.
    auto styleNamesSorted = getMixingOrder(_styles);

    for (const auto& name : styleNamesSorted) {

        const auto& style = _styles[name];

        if (!style || !style.IsMap()) {
            // Something's wrong here, try the next one!
            continue;
        }

        // For each style to evaluate, get the list of styles that need to be mixed with this one.
        auto stylesToMix = getStylesToMix(style);

        std::vector<Node> mixins;
        for (const auto& styleNameToMix : stylesToMix) {

            // Skip mixing built-in styles.
            const auto& builtIn = Style::builtInStyleNames();
            if (std::find(builtIn.begin(), builtIn.end(), styleNameToMix) != builtIn.end()) {
                continue;
            }

            mixins.push_back(_styles[styleNameToMix]);
        }

        applyStyleMixins(style, mixins);
    }
}

void StyleMixer::applyStyleMixins(Node _style, const std::vector<Node>& _mixins) {

    // Merge boolean flags as a disjunction.
    mergeBooleanFieldAsDisjunction("animated", _style, _mixins);
    mergeBooleanFieldAsDisjunction("texcoords", _style, _mixins);

    // Merge scalar fields with newer values taking precedence.
    mergeFieldTakingLast("base", _style, _mixins);
    mergeFieldTakingLast("lighting", _style, _mixins);
    mergeFieldTakingLast("texture", _style, _mixins);
    mergeFieldTakingLast("blend", _style, _mixins);
    mergeFieldTakingLast("blend_order", _style, _mixins);

    // Merge map fields with newer values taking precedence.
    mergeMapFieldTakingLast("material", _style, _mixins);

    // Produce a list of all 'mixins' with shader nodes and merge those separately.
    std::vector<Node> shaderMixins;
    for (const auto& mixin : _mixins) {
        if (const auto& shaders = mixin["shaders"]) {
            shaderMixins.push_back(shaders);
        }
    }
    applyShaderMixins(_style["shaders"], shaderMixins);
}

void StyleMixer::applyShaderMixins(Node _shaders, const std::vector<Node>& _mixins) {

    // Merge maps fields with newer values taking precedence.
    mergeMapFieldTakingLast("defines", _shaders, _mixins);
    mergeMapFieldTakingLast("uniforms", _shaders, _mixins);

    // Merge "extensions" as a non-repeating set.
    {
        std::set<std::string> set;
        Node output = _shaders["extensions_mixed"];
        output = Node(); // Clear this node in case something was already there.
        for (const auto& mixin : _mixins) {
            Node extensions = mixin["extensions_mixed"];
            for (const auto& e : extensions) {
                set.insert(e.Scalar());
            }
        }
        Node extensions = _shaders["extensions"];
        if (extensions.IsScalar()) {
            set.insert(extensions.Scalar());
        } else if (extensions.IsSequence()) {
            for (const auto& e : extensions) {
                set.insert(e.Scalar());
            }
        }
        for (const auto& extension : set) {
            output.push_back(extension);
        }
    }

    // Merge "blocks" into a list of strings for each key.
    {
        Node output = _shaders["blocks_mixed"];
        output = Node(); // Clear this node in case something was already there.
        for (const auto& mixin : _mixins) {
            Node blocks = mixin["blocks_mixed"];
            for (const auto& entry : blocks) {
                Node list = output[entry.first.Scalar()];
                for (const auto& block : entry.second) {
                    // If the list already contains an exact reference to the same node,
                    // don't add it again.
                    if (std::find(list.begin(), list.end(), block) == list.end()) {
                        list.push_back(block);
                    }
                }
            }
        }
        for (const auto& entry : _shaders["blocks"]) {
            output[entry.first.Scalar()].push_back(entry.second.Scalar());
        }
    }
}

void StyleMixer::mergeBooleanFieldAsDisjunction(std::string key, Node target, const std::vector<Node>& sources) {

    auto current = target[key];
    if (current && current.as<bool>(false)) {
        // Target field is already true, we can stop here.
        return;
    }

    for (const auto& source : sources) {
        const auto& value = source[key];
        if (value && value.as<bool>(false)) {
            target[key] = true;
            return;
        }
    }
}

void StyleMixer::mergeFieldTakingLast(std::string key, Node target, const std::vector<Node>& sources) {

    if (target[key]) {
        // Target already has a value, we can stop here.
        return;
    }

    for (auto it = sources.rbegin(); it != sources.rend(); ++it) {
        const auto& value = (*it)[key];
        if (value) {
            target[key] = value;
            return;
        }
    }
}

void StyleMixer::mergeMapFieldTakingLast(std::string key, Node target, const std::vector<Node>& sources) {

    Node map = target[key];
    if (!map || !map.IsMap()) {
        return;
    }
    for (auto it = sources.rbegin(); it != sources.rend(); ++it) {
        const auto& source = (*it)[key];
        if (!source.IsMap()) {
            continue;
        }
        for (const auto& entry : source) {
            const auto& subkey = entry.first.Scalar();
            if (!map[subkey]) {
                map[subkey] = entry.second;
            }
        }
    }

}

}
<commit_msg>Fix: Merging a style map property<commit_after>#include "styleMixer.h"
#include "style/style.h"
#include "util/topologicalSort.h"
#include "yaml-cpp/yaml.h"

#include <algorithm>
#include <set>

namespace Tangram {

std::vector<std::string> StyleMixer::getStylesToMix(const Node& _style) {

    std::vector<std::string> names;

    // 'base' style is the first item to mix.
    if (const Node& base = _style["base"]) {
        if (base.IsScalar()) { names.push_back(base.Scalar()); }
    }

    // 'mix' styles are mixed next, in order of declaration.
    if (const Node& mix = _style["mix"]) {
        if (mix.IsScalar()) {
            names.push_back(mix.Scalar());
        } else if (mix.IsSequence()) {
            for (const auto& m : mix) {
                if (m.IsScalar()) { names.push_back(m.Scalar()); }
            }
        }
    }

    return names;
}

std::vector<std::string> StyleMixer::getMixingOrder(const Node& _styles) {

    // Input must be a map of names to style configuration nodes.
    if (!_styles.IsMap()) {
        return {};
    }

    // Dependencies are pairs of strings that form a DAG.
    // If style 'a' mixes style 'b', the dependency would be {'b', 'a'}.
    std::vector<std::pair<std::string, std::string>> dependencies;

    for (const auto& entry : _styles) {
        const auto& name = entry.first;
        const auto& config = entry.second;
        for (const auto& mix : getStylesToMix(config)) {
            dependencies.push_back({ mix, name.Scalar() });
        }
    }

    return topologicalSort(dependencies);
}

void StyleMixer::mixStyleNodes(Node _styles) {

    // First determine the order of nodes to evaluate.
    auto styleNamesSorted = getMixingOrder(_styles);

    for (const auto& name : styleNamesSorted) {

        const auto& style = _styles[name];

        if (!style || !style.IsMap()) {
            // Something's wrong here, try the next one!
            continue;
        }

        // For each style to evaluate, get the list of styles that need to be mixed with this one.
        auto stylesToMix = getStylesToMix(style);

        std::vector<Node> mixins;
        for (const auto& styleNameToMix : stylesToMix) {

            // Skip mixing built-in styles.
            const auto& builtIn = Style::builtInStyleNames();
            if (std::find(builtIn.begin(), builtIn.end(), styleNameToMix) != builtIn.end()) {
                continue;
            }

            mixins.push_back(_styles[styleNameToMix]);
        }

        applyStyleMixins(style, mixins);
    }
}

void StyleMixer::applyStyleMixins(Node _style, const std::vector<Node>& _mixins) {

    // Merge boolean flags as a disjunction.
    mergeBooleanFieldAsDisjunction("animated", _style, _mixins);
    mergeBooleanFieldAsDisjunction("texcoords", _style, _mixins);

    // Merge scalar fields with newer values taking precedence.
    mergeFieldTakingLast("base", _style, _mixins);
    mergeFieldTakingLast("lighting", _style, _mixins);
    mergeFieldTakingLast("texture", _style, _mixins);
    mergeFieldTakingLast("blend", _style, _mixins);
    mergeFieldTakingLast("blend_order", _style, _mixins);

    // Merge map fields with newer values taking precedence.
    mergeMapFieldTakingLast("material", _style, _mixins);

    // Produce a list of all 'mixins' with shader nodes and merge those separately.
    std::vector<Node> shaderMixins;
    for (const auto& mixin : _mixins) {
        if (const auto& shaders = mixin["shaders"]) {
            shaderMixins.push_back(shaders);
        }
    }
    applyShaderMixins(_style["shaders"], shaderMixins);
}

void StyleMixer::applyShaderMixins(Node _shaders, const std::vector<Node>& _mixins) {

    // Merge maps fields with newer values taking precedence.
    mergeMapFieldTakingLast("defines", _shaders, _mixins);
    mergeMapFieldTakingLast("uniforms", _shaders, _mixins);

    // Merge "extensions" as a non-repeating set.
    {
        std::set<std::string> set;
        Node output = _shaders["extensions_mixed"];
        output = Node(); // Clear this node in case something was already there.
        for (const auto& mixin : _mixins) {
            Node extensions = mixin["extensions_mixed"];
            for (const auto& e : extensions) {
                set.insert(e.Scalar());
            }
        }
        Node extensions = _shaders["extensions"];
        if (extensions.IsScalar()) {
            set.insert(extensions.Scalar());
        } else if (extensions.IsSequence()) {
            for (const auto& e : extensions) {
                set.insert(e.Scalar());
            }
        }
        for (const auto& extension : set) {
            output.push_back(extension);
        }
    }

    // Merge "blocks" into a list of strings for each key.
    {
        Node output = _shaders["blocks_mixed"];
        output = Node(); // Clear this node in case something was already there.
        for (const auto& mixin : _mixins) {
            Node blocks = mixin["blocks_mixed"];
            for (const auto& entry : blocks) {
                Node list = output[entry.first.Scalar()];
                for (const auto& block : entry.second) {
                    // If the list already contains an exact reference to the same node,
                    // don't add it again.
                    if (std::find(list.begin(), list.end(), block) == list.end()) {
                        list.push_back(block);
                    }
                }
            }
        }
        for (const auto& entry : _shaders["blocks"]) {
            output[entry.first.Scalar()].push_back(entry.second.Scalar());
        }
    }
}

void StyleMixer::mergeBooleanFieldAsDisjunction(std::string key, Node target, const std::vector<Node>& sources) {

    auto current = target[key];
    if (current && current.as<bool>(false)) {
        // Target field is already true, we can stop here.
        return;
    }

    for (const auto& source : sources) {
        const auto& value = source[key];
        if (value && value.as<bool>(false)) {
            target[key] = true;
            return;
        }
    }
}

void StyleMixer::mergeFieldTakingLast(std::string key, Node target, const std::vector<Node>& sources) {

    if (target[key]) {
        // Target already has a value, we can stop here.
        return;
    }

    for (auto it = sources.rbegin(); it != sources.rend(); ++it) {
        const auto& value = (*it)[key];
        if (value) {
            target[key] = value;
            return;
        }
    }
}

void StyleMixer::mergeMapFieldTakingLast(std::string key, Node target, const std::vector<Node>& sources) {

    Node map = target[key];
    if (map && !map.IsMap()) { return; }

    for (auto it = sources.rbegin(); it != sources.rend(); ++it) {
        const auto& source = (*it)[key];
        if (!source.IsMap()) {
            continue;
        }
        for (const auto& entry : source) {
            const auto& subkey = entry.first.Scalar();
            if (!map[subkey]) {
                map[subkey] = entry.second;
            }
        }
    }

}

}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkImageInPlaceFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$
  Thanks:    Thanks to C. Charles Law who developed this class.

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkImageCache.h"
#include "vtkImageInPlaceFilter.h"

//----------------------------------------------------------------------------
// Description:
// This method is called by the cache.  It eventually calls the
// Execute(vtkImageData *, vtkImageData *) method.
// ImageInformation has already been updated by this point,
// and outRegion is in local coordinates.
// This method will stream to get the input, and loops over extra axes.
// Only the UpdateExtent from output will get updated.
void vtkImageInPlaceFilter::InternalUpdate(vtkImageData *outData)
{
  int *inExt, *outExt;

  // Make sure the Input has been set.
  if ( ! this->Input)
    {
    vtkErrorMacro(<< "Input is not set.");
    return;
    }

  // prevent infinite update loops.
  if (this->Updating)
    {
    return;
    }
  this->Updating = 1;

  // Make sure there is an output.
  this->CheckCache();

  // In case this update is called directly.
  this->UpdateImageInformation();
  this->Output->ClipUpdateExtentWithWholeExtent();

  // Handle bypass condition.
  if (this->Bypass)
    {
    vtkImageData *inData;

    this->Input->SetUpdateExtent(this->Output->GetUpdateExtent());
    inData = this->Input->UpdateAndReturnData();
    if (!inData)
      {
      vtkWarningMacro("No input data provided!");
      }
    else
      {
      outData->GetPointData()->PassData(inData->GetPointData());
      }

    // release input data
    if (this->Input->ShouldIReleaseData())
      {
      this->Input->ReleaseData();
      }
    this->Updating = 0;
    return;
    }

  // since this is an in place filter the input and output extents
  // better be the same. And the Release Flag better be set to
  // release ELSE we do the normal out of place filtering
  inExt = this->Input->GetUpdateExtent();
  outExt = this->Output->GetUpdateExtent();
  if ((inExt[0] == outExt[0])&&(inExt[1] == outExt[1])&&
      (inExt[2] == outExt[2])&&(inExt[3] == outExt[3])&&
      (inExt[4] == outExt[4])&&(inExt[5] == outExt[5])&&
      this->Input->ShouldIReleaseData())
    {
    vtkImageData *inData;
    inData = this->Input->UpdateAndReturnData();

    // pass the data
    outData->GetPointData()->PassData(inData->GetPointData());

    // The StartMethod call is placed here to be after updating the input.
    if ( this->StartMethod ) (*this->StartMethod)(this->StartMethodArg);
    // fill the output region
    this->Execute(inData, outData);
    if ( this->EndMethod ) (*this->EndMethod)(this->EndMethodArg);

    // Like the graphics pipeline this source releases inputs data.
    this->Input->ReleaseData();
    }
  else
    {
    this->RecursiveStreamUpdate(outData,2);
    }

  this->Updating = 0;
}

//----------------------------------------------------------------------------
// Description:
// This method can be called recursively for streaming.
// The extent of the outRegion changes, dim remains the same.
// Same as the one in Filter except that it copies the data
// before executing
void vtkImageInPlaceFilter::RecursiveStreamUpdate(vtkImageData *outData,
						  int splitAxis)
{
  int memory;
  vtkImageData *inData;

  // Compute the required input region extent.
  // Copy to fill in extent of extra dimensions.
  this->ComputeRequiredInputUpdateExtent(this->Input->GetUpdateExtent(),
					 this->Output->GetUpdateExtent());

  // determine the amount of memory that will be used by the input region.
  memory = this->Input->GetUpdateExtentMemorySize();

  // Split the inRegion if we are streaming.
  if ((memory > this->Input->GetMemoryLimit()))
    {
    int min, max, mid;
    this->Output->GetAxisUpdateExtent(splitAxis,min,max);
    while ( (min == max) && splitAxis > 0)
      {
      splitAxis--;
      this->Output->GetAxisUpdateExtent(splitAxis,min,max);
      }
    // Make sure we can actually split the axis
    if (min < max)
      {
      // Set the first half to update
      mid = (min + max) / 2;
      vtkDebugMacro(<< "RecursiveStreamUpdate: Splitting "
      << splitAxis << " : memory = " << memory <<
      ", extent = " << min << "->" << mid << " | " << mid+1 << "->" << max);
      this->Output->SetAxisUpdateExtent(splitAxis, min, mid);
      this->RecursiveStreamUpdate(outData, splitAxis);
      // Set the second half to update
      this->Output->SetAxisUpdateExtent(splitAxis, mid+1, max);
      this->RecursiveStreamUpdate(outData, splitAxis);
      // Restore the original extent
      this->Output->SetAxisUpdateExtent(splitAxis, min, max);
      return;
      }
    else
      {
      // Cannot split any more.  Ignore memory limit and continue.
      vtkWarningMacro(<< "RecursiveStreamUpdate: Cannot split. memory = "
        << memory << ", " << splitAxis << " : " << min << "->" << max);
      }
    }

  // No Streaming required.
  // Get the input region (Update extent was set at start of this method).
  inData = this->Input->UpdateAndReturnData();

  // The StartMethod call is placed here to be after updating the input.
  if ( this->StartMethod ) (*this->StartMethod)(this->StartMethodArg);
  // fill the output region
  // copy the data first
  this->CopyData(inData,outData);
  this->Execute(inData, outData);
  if ( this->EndMethod ) (*this->EndMethod)(this->EndMethodArg);

  // Like the graphics pipeline this source releases inputs data.
  if (this->Input->ShouldIReleaseData())
    {
    this->Input->ReleaseData();
    }
}

void vtkImageInPlaceFilter::CopyData(vtkImageData *inData,
				     vtkImageData *outData)
{
  int *outExt = this->Output->GetUpdateExtent();
  void *inPtr = inData->GetScalarPointerForExtent(outExt);
  void *outPtr = outData->GetScalarPointerForExtent(outExt);
  int rowLength, size;
  int inIncX, inIncY, inIncZ;
  int outIncX, outIncY, outIncZ;
  int idxY, idxZ, maxY, maxZ;

  rowLength = (outExt[1] - outExt[0]+1)*inData->GetNumberOfScalarComponents();
  size = inData->GetScalarSize();
  rowLength *= size;
  maxY = outExt[3] - outExt[2];
  maxZ = outExt[5] - outExt[4];

  // Get increments to march through data
  inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
  outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);

  // adjust increments for this loop
  inIncY = inIncY*size + rowLength;
  outIncY = outIncY*size + rowLength;
  inIncZ *= size;
  outIncZ *= size;

  // Loop through ouput pixels
  for (idxZ = 0; idxZ <= maxZ; idxZ++)
    {
    for (idxY = 0; idxY <= maxY; idxY++)
      {
      memcpy(outPtr,inPtr,rowLength);
      outPtr += outIncY;
      inPtr += inIncY;
      }
    outPtr += outIncZ;
    inPtr += inIncZ;
    }
}
<commit_msg>ERR: vodi * must be char *<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageInPlaceFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$
  Thanks:    Thanks to C. Charles Law who developed this class.

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkImageCache.h"
#include "vtkImageInPlaceFilter.h"

//----------------------------------------------------------------------------
// Description:
// This method is called by the cache.  It eventually calls the
// Execute(vtkImageData *, vtkImageData *) method.
// ImageInformation has already been updated by this point,
// and outRegion is in local coordinates.
// This method will stream to get the input, and loops over extra axes.
// Only the UpdateExtent from output will get updated.
void vtkImageInPlaceFilter::InternalUpdate(vtkImageData *outData)
{
  int *inExt, *outExt;

  // Make sure the Input has been set.
  if ( ! this->Input)
    {
    vtkErrorMacro(<< "Input is not set.");
    return;
    }

  // prevent infinite update loops.
  if (this->Updating)
    {
    return;
    }
  this->Updating = 1;

  // Make sure there is an output.
  this->CheckCache();

  // In case this update is called directly.
  this->UpdateImageInformation();
  this->Output->ClipUpdateExtentWithWholeExtent();

  // Handle bypass condition.
  if (this->Bypass)
    {
    vtkImageData *inData;

    this->Input->SetUpdateExtent(this->Output->GetUpdateExtent());
    inData = this->Input->UpdateAndReturnData();
    if (!inData)
      {
      vtkWarningMacro("No input data provided!");
      }
    else
      {
      outData->GetPointData()->PassData(inData->GetPointData());
      }

    // release input data
    if (this->Input->ShouldIReleaseData())
      {
      this->Input->ReleaseData();
      }
    this->Updating = 0;
    return;
    }

  // since this is an in place filter the input and output extents
  // better be the same. And the Release Flag better be set to
  // release ELSE we do the normal out of place filtering
  inExt = this->Input->GetUpdateExtent();
  outExt = this->Output->GetUpdateExtent();
  if ((inExt[0] == outExt[0])&&(inExt[1] == outExt[1])&&
      (inExt[2] == outExt[2])&&(inExt[3] == outExt[3])&&
      (inExt[4] == outExt[4])&&(inExt[5] == outExt[5])&&
      this->Input->ShouldIReleaseData())
    {
    vtkImageData *inData;
    inData = this->Input->UpdateAndReturnData();

    // pass the data
    outData->GetPointData()->PassData(inData->GetPointData());

    // The StartMethod call is placed here to be after updating the input.
    if ( this->StartMethod ) (*this->StartMethod)(this->StartMethodArg);
    // fill the output region
    this->Execute(inData, outData);
    if ( this->EndMethod ) (*this->EndMethod)(this->EndMethodArg);

    // Like the graphics pipeline this source releases inputs data.
    this->Input->ReleaseData();
    }
  else
    {
    this->RecursiveStreamUpdate(outData,2);
    }

  this->Updating = 0;
}

//----------------------------------------------------------------------------
// Description:
// This method can be called recursively for streaming.
// The extent of the outRegion changes, dim remains the same.
// Same as the one in Filter except that it copies the data
// before executing
void vtkImageInPlaceFilter::RecursiveStreamUpdate(vtkImageData *outData,
						  int splitAxis)
{
  int memory;
  vtkImageData *inData;

  // Compute the required input region extent.
  // Copy to fill in extent of extra dimensions.
  this->ComputeRequiredInputUpdateExtent(this->Input->GetUpdateExtent(),
					 this->Output->GetUpdateExtent());

  // determine the amount of memory that will be used by the input region.
  memory = this->Input->GetUpdateExtentMemorySize();

  // Split the inRegion if we are streaming.
  if ((memory > this->Input->GetMemoryLimit()))
    {
    int min, max, mid;
    this->Output->GetAxisUpdateExtent(splitAxis,min,max);
    while ( (min == max) && splitAxis > 0)
      {
      splitAxis--;
      this->Output->GetAxisUpdateExtent(splitAxis,min,max);
      }
    // Make sure we can actually split the axis
    if (min < max)
      {
      // Set the first half to update
      mid = (min + max) / 2;
      vtkDebugMacro(<< "RecursiveStreamUpdate: Splitting "
      << splitAxis << " : memory = " << memory <<
      ", extent = " << min << "->" << mid << " | " << mid+1 << "->" << max);
      this->Output->SetAxisUpdateExtent(splitAxis, min, mid);
      this->RecursiveStreamUpdate(outData, splitAxis);
      // Set the second half to update
      this->Output->SetAxisUpdateExtent(splitAxis, mid+1, max);
      this->RecursiveStreamUpdate(outData, splitAxis);
      // Restore the original extent
      this->Output->SetAxisUpdateExtent(splitAxis, min, max);
      return;
      }
    else
      {
      // Cannot split any more.  Ignore memory limit and continue.
      vtkWarningMacro(<< "RecursiveStreamUpdate: Cannot split. memory = "
        << memory << ", " << splitAxis << " : " << min << "->" << max);
      }
    }

  // No Streaming required.
  // Get the input region (Update extent was set at start of this method).
  inData = this->Input->UpdateAndReturnData();

  // The StartMethod call is placed here to be after updating the input.
  if ( this->StartMethod ) (*this->StartMethod)(this->StartMethodArg);
  // fill the output region
  // copy the data first
  this->CopyData(inData,outData);
  this->Execute(inData, outData);
  if ( this->EndMethod ) (*this->EndMethod)(this->EndMethodArg);

  // Like the graphics pipeline this source releases inputs data.
  if (this->Input->ShouldIReleaseData())
    {
    this->Input->ReleaseData();
    }
}

void vtkImageInPlaceFilter::CopyData(vtkImageData *inData,
				     vtkImageData *outData)
{
  int *outExt = this->Output->GetUpdateExtent();
  char *inPtr = (char *) inData->GetScalarPointerForExtent(outExt);
  char *outPtr = (char *) outData->GetScalarPointerForExtent(outExt);
  int rowLength, size;
  int inIncX, inIncY, inIncZ;
  int outIncX, outIncY, outIncZ;
  int idxY, idxZ, maxY, maxZ;

  rowLength = (outExt[1] - outExt[0]+1)*inData->GetNumberOfScalarComponents();
  size = inData->GetScalarSize();
  rowLength *= size;
  maxY = outExt[3] - outExt[2];
  maxZ = outExt[5] - outExt[4];

  // Get increments to march through data
  inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
  outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);

  // adjust increments for this loop
  inIncY = inIncY*size + rowLength;
  outIncY = outIncY*size + rowLength;
  inIncZ *= size;
  outIncZ *= size;

  // Loop through ouput pixels
  for (idxZ = 0; idxZ <= maxZ; idxZ++)
    {
    for (idxY = 0; idxY <= maxY; idxY++)
      {
      memcpy(outPtr,inPtr,rowLength);
      outPtr += outIncY;
      inPtr += inIncY;
      }
    outPtr += outIncZ;
    inPtr += inIncZ;
    }
}
<|endoftext|>


<commit_before>#include "fontContext.h"
#define FONTSTASH_IMPLEMENTATION
#include "fontstash.h"

namespace Tangram {

FontContext::FontContext() : FontContext(512) {}

FontContext::FontContext(int _atlasSize) {
    initFontContext(_atlasSize);
}

FontContext::~FontContext() {
    fonsDeleteInternal(m_fsContext);
}

void FontContext::bindAtlas(GLuint _textureUnit) {
    {
        std::lock_guard<std::mutex> lock(m_atlasMutex);
        m_atlas->update(_textureUnit);
    }
    m_atlas->bind(_textureUnit);
}

void FontContext::clearState() {
    fonsClearState(m_fsContext);
}

bool FontContext::lock() {
    try {
        m_contextMutex.lock();
    } catch (std::system_error& e) {
        LOGW("Dead lock: aborting");
        return false;
    }
    return true;
}

void FontContext::unlock() {
    m_contextMutex.unlock();
}

bool FontContext::addFont(const std::string& _family, const std::string& _weight, const std::string& _style) {

    std::string fontKey = _family + "_" + _weight + "_" + _style;
    if (m_fonts.find(fontKey) != m_fonts.end()) {
        return true;
    }

    unsigned int dataSize;
    unsigned char* data = nullptr;

    // Assuming bundled ttf file follows this convention
    auto bundledFontPath = "fonts/" + _family + "-" + _weight + _style + ".ttf";
    if (!(data = bytesFromFile(bundledFontPath.c_str(), PathType::resource, &dataSize)) &&
        !(data = bytesFromFile(bundledFontPath.c_str(), PathType::internal, &dataSize))) {
        const std::string sysFontPath = systemFontPath(_family, _weight, _style);
        if ( !(data = bytesFromFile(sysFontPath.c_str(), PathType::absolute, &dataSize)) ) {
            return false;
        }
    }

    int font = fonsAddFont(m_fsContext, fontKey.c_str(), data, dataSize);

    if (font == FONS_INVALID) {
        LOGE("loading font %s", fontKey.c_str());
        return false;
    }

    m_fonts.emplace(std::move(fontKey), font);

    return true;
}

void FontContext::setFont(const std::string& _key, int size) {
    FontID id = getFontID(_key);

    if (id >= 0) {
        fonsSetSize(m_fsContext, size);
        fonsSetFont(m_fsContext, id);
    } else {
        LOGW("Could not find font %s", _key.c_str());
    }
}

FontID FontContext::getFontID(const std::string& _key) {
    auto it = m_fonts.find(_key);

    if (it != m_fonts.end()) {
        return it->second;
    }

    if (m_fonts.size() > 0) {
        // sceneLoader makes sure that first loaded font is the default bundled font
        LOGW("Using default font for '%s'.", _key.c_str());
        m_fonts.emplace(_key, 0);
        return 0;
    } else {
        LOGE("No default font loaded.");
        return -1;
    }
}

std::vector<FONSquad>& FontContext::rasterize(const std::string& _text, FontID _fontID, float _fontSize, float _sdf) {

    m_quadBuffer.clear();

    fonsSetSize(m_fsContext, _fontSize);
    fonsSetFont(m_fsContext, _fontID);

    if (_sdf > 0){
        fonsSetBlur(m_fsContext, _sdf);
        fonsSetBlurType(m_fsContext, FONS_EFFECT_DISTANCE_FIELD);
    } else {
        fonsSetBlurType(m_fsContext, FONS_EFFECT_NONE);
    }

    float advance = fonsDrawText(m_fsContext, 0, 0, _text.c_str(), nullptr, 0);
    if (advance < 0) {
        m_quadBuffer.clear();
        return m_quadBuffer;
    }

    return m_quadBuffer;
}

void FontContext::pushQuad(void* _userPtr, const FONSquad* _quad) {
    FontContext* fontContext = static_cast<FontContext*>(_userPtr);
    fontContext->m_quadBuffer.emplace_back(*_quad);
}

int FontContext::renderCreate(void* _userPtr, int _width, int _height) {
    return 1;
}

void FontContext::renderUpdate(void* _userPtr, int* _rect, const unsigned char* _data) {
    FontContext* fontContext = static_cast<FontContext*>(_userPtr);

    uint32_t xoff = 0;
    uint32_t yoff = _rect[1];
    uint32_t width = fontContext->m_atlas->getWidth();
    uint32_t height = _rect[3] - _rect[1];

    auto subdata = reinterpret_cast<const GLuint*>(_data + yoff * width);

    std::lock_guard<std::mutex> lock(fontContext->m_atlasMutex);
    fontContext->m_atlas->setSubData(subdata, xoff, yoff, width, height);
}

void FontContext::initFontContext(int _atlasSize) {
    m_atlas = std::unique_ptr<Texture>(new Texture(_atlasSize, _atlasSize));

    FONSparams params;
    params.width = _atlasSize;
    params.height = _atlasSize;
    params.flags = (unsigned char)FONS_ZERO_TOPLEFT;

    params.renderCreate = renderCreate;
    params.renderResize = nullptr;
    params.renderUpdate = renderUpdate;
    params.renderDraw = nullptr;
    params.renderDelete = nullptr;
    params.pushQuad = pushQuad;
    params.userPtr = (void*) this;

    m_fsContext = fonsCreateInternal(&params);;
}

}
<commit_msg>dont try to load inavalid fonts twice<commit_after>#include "fontContext.h"
#define FONTSTASH_IMPLEMENTATION
#include "fontstash.h"

namespace Tangram {

FontContext::FontContext() : FontContext(512) {}

FontContext::FontContext(int _atlasSize) {
    initFontContext(_atlasSize);
}

FontContext::~FontContext() {
    fonsDeleteInternal(m_fsContext);
}

void FontContext::bindAtlas(GLuint _textureUnit) {
    {
        std::lock_guard<std::mutex> lock(m_atlasMutex);
        m_atlas->update(_textureUnit);
    }
    m_atlas->bind(_textureUnit);
}

void FontContext::clearState() {
    fonsClearState(m_fsContext);
}

bool FontContext::lock() {
    try {
        m_contextMutex.lock();
    } catch (std::system_error& e) {
        LOGW("Dead lock: aborting");
        return false;
    }
    return true;
}

void FontContext::unlock() {
    m_contextMutex.unlock();
}

bool FontContext::addFont(const std::string& _family, const std::string& _weight, const std::string& _style) {

    std::string fontKey = _family + "_" + _weight + "_" + _style;
    if (m_fonts.find(fontKey) != m_fonts.end()) {
        return true;
    }

    unsigned int dataSize;
    unsigned char* data = nullptr;

    // Assuming bundled ttf file follows this convention
    auto bundledFontPath = "fonts/" + _family + "-" + _weight + _style + ".ttf";
    if (!(data = bytesFromFile(bundledFontPath.c_str(), PathType::resource, &dataSize)) &&
        !(data = bytesFromFile(bundledFontPath.c_str(), PathType::internal, &dataSize))) {
        const std::string sysFontPath = systemFontPath(_family, _weight, _style);
        if ( !(data = bytesFromFile(sysFontPath.c_str(), PathType::absolute, &dataSize)) ) {
            logMsg("[FontContext] Error loading font file %s\n", fontKey.c_str());
            m_fonts.emplace(std::move(fontKey), FONS_INVALID);
            return false;
        }
    }

    int font = fonsAddFont(m_fsContext, fontKey.c_str(), data, dataSize);

    if (font == FONS_INVALID) {
        LOGE("loading font %s", fontKey.c_str());
        return false;
    }

    m_fonts.emplace(std::move(fontKey), font);

    return true;
}

void FontContext::setFont(const std::string& _key, int size) {
    FontID id = getFontID(_key);

    if (id >= 0) {
        fonsSetSize(m_fsContext, size);
        fonsSetFont(m_fsContext, id);
    } else {
        LOGW("Could not find font %s", _key.c_str());
    }
}

FontID FontContext::getFontID(const std::string& _key) {
    auto it = m_fonts.find(_key);

    if (it != m_fonts.end()) {
        return it->second;
    }

    if (m_fonts.size() > 0) {
        // sceneLoader makes sure that first loaded font is the default bundled font
        LOGW("Using default font for '%s'.", _key.c_str());
        m_fonts.emplace(_key, 0);
        return 0;
    } else {
        LOGE("No default font loaded.");
        return -1;
    }
}

std::vector<FONSquad>& FontContext::rasterize(const std::string& _text, FontID _fontID, float _fontSize, float _sdf) {

    m_quadBuffer.clear();

    fonsSetSize(m_fsContext, _fontSize);
    fonsSetFont(m_fsContext, _fontID);

    if (_sdf > 0){
        fonsSetBlur(m_fsContext, _sdf);
        fonsSetBlurType(m_fsContext, FONS_EFFECT_DISTANCE_FIELD);
    } else {
        fonsSetBlurType(m_fsContext, FONS_EFFECT_NONE);
    }

    float advance = fonsDrawText(m_fsContext, 0, 0, _text.c_str(), nullptr, 0);
    if (advance < 0) {
        m_quadBuffer.clear();
        return m_quadBuffer;
    }

    return m_quadBuffer;
}

void FontContext::pushQuad(void* _userPtr, const FONSquad* _quad) {
    FontContext* fontContext = static_cast<FontContext*>(_userPtr);
    fontContext->m_quadBuffer.emplace_back(*_quad);
}

int FontContext::renderCreate(void* _userPtr, int _width, int _height) {
    return 1;
}

void FontContext::renderUpdate(void* _userPtr, int* _rect, const unsigned char* _data) {
    FontContext* fontContext = static_cast<FontContext*>(_userPtr);

    uint32_t xoff = 0;
    uint32_t yoff = _rect[1];
    uint32_t width = fontContext->m_atlas->getWidth();
    uint32_t height = _rect[3] - _rect[1];

    auto subdata = reinterpret_cast<const GLuint*>(_data + yoff * width);

    std::lock_guard<std::mutex> lock(fontContext->m_atlasMutex);
    fontContext->m_atlas->setSubData(subdata, xoff, yoff, width, height);
}

void FontContext::initFontContext(int _atlasSize) {
    m_atlas = std::unique_ptr<Texture>(new Texture(_atlasSize, _atlasSize));

    FONSparams params;
    params.width = _atlasSize;
    params.height = _atlasSize;
    params.flags = (unsigned char)FONS_ZERO_TOPLEFT;

    params.renderCreate = renderCreate;
    params.renderResize = nullptr;
    params.renderUpdate = renderUpdate;
    params.renderDraw = nullptr;
    params.renderDelete = nullptr;
    params.pushQuad = pushQuad;
    params.userPtr = (void*) this;

    m_fsContext = fonsCreateInternal(&params);;
}

}
<|endoftext|>


<commit_before>/*
The default runner expects:

- to have TEST_FUNC defined to the Halide pipeline name being tested
- to have TEST_IN_T/TEST_OUT_T defined to the type name for the input/output buffer of TEST_FUNC
    e.g. `float` or `uint8_t`
- to have libpng in the include path, and linked into the resulting binary:
    e.g. `$(libpng-config --cflags --ldflags)`
- to be compiled in the same directory with <TEST_FUNC>.h
- to have the Halide/support directory in its include path, for static_image.h/image_io.h
*/

#ifndef TEST_FUNC
#error default_runner must be compiled with TEST_FUNC defined
#endif
#define TEST_HEADER TEST_FUNC.h

// Utilities to paste a macro as a string constant in another macro.
// via: http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
#define str(s) xstr(s)
#define xstr(s) #s

extern "C" {
#include str(TEST_HEADER)
}
#include <static_image.h>
#include <image_io.h>

#include <sys/time.h>

#include <string>
using std::string;

static const string usage = "Usage:\n\
\trunner <test iterations> <input_image.png> [reference_output.png] [w|-1] [h|-1] [channels|-1] [save_output.png]";

template<class T>
bool images_equal(Image<T> &a, Image<T> &b, T eps) {
    if (a.width() != b.width() || a.height() != b.height() || a.channels() != b.channels()) {
        return false;
    }
    for (int c = 0; c < a.channels(); c++) {
        for (int y = 0; y < a.height(); y++) {
            for (int x = 0; x < a.width(); x++) {
                T ac = a(x,y,c);
                T bc = b(x,y,c);
                T delta = ac > bc ? ac - bc: bc - ac;
                if (delta > eps) { return false; }
            }
        }
    }
    return true;
}

int main(int argc, char const *argv[])
{
    if (argc < 3) {
        fprintf(stderr, "%s\n", usage.c_str());
        return -1;
    }

    int test_iterations = atoi(argv[1]);

    timeval t1, t2;
    unsigned int t;
    gettimeofday(&t1, NULL);
    Image<TEST_IN_T> input = load<TEST_IN_T>(argv[2]);
    gettimeofday(&t2, NULL);
    t = (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec);
    printf("load time input: %.4f secs\n", t);
    int w        = argc > 4 ? atoi(argv[4]): -1;
    int h        = argc > 5 ? atoi(argv[5]): -1;
    int channels = argc > 6 ? atoi(argv[6]): -1;
    char const *save_output = argc > 7 ? argv[7]: NULL;

    if (w < 0) { w = input.width(); }
    if (h < 0) { h = input.height(); }
    if (channels < 0) { channels = input.channels(); }

    Image<TEST_OUT_T> output(w, h, channels);
    Image<TEST_OUT_T> ref_output(1,1,1);
    bool has_ref = false;
    if (argc > 3 && strcmp(argv[3], "") != 0) {
        gettimeofday(&t1, NULL);
        ref_output = load<TEST_OUT_T>(argv[3]);
        gettimeofday(&t2, NULL);
        t = (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec);
        printf("load time output: %.4f secs\n", t);
        has_ref = true;
    }

    // Timing code
    unsigned int bestT = 0xffffffff;
    for (int i = 0; i < test_iterations; i++) {
        gettimeofday(&t1, NULL);
        TEST_FUNC(input, output);
        gettimeofday(&t2, NULL);
        t = (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec);
        if (t < bestT) bestT = t;
    }

    // Saving large PNGs is expensive. Only do it if enabled.
    if (save_output != NULL && strcmp(save_output, "") != 0) {
        save(output, save_output);
    }

    if (has_ref) {
        if (!images_equal<TEST_OUT_T>(ref_output, output, 0.01)) {
            printf("RUN_CHECK_FAIL\n");
            exit(1);
        }
    }
    printf("Success %f\n", bestT/1000000.0);

    return 0;
}
<commit_msg>py bindings -- time in runner (fix)<commit_after>/*
The default runner expects:

- to have TEST_FUNC defined to the Halide pipeline name being tested
- to have TEST_IN_T/TEST_OUT_T defined to the type name for the input/output buffer of TEST_FUNC
    e.g. `float` or `uint8_t`
- to have libpng in the include path, and linked into the resulting binary:
    e.g. `$(libpng-config --cflags --ldflags)`
- to be compiled in the same directory with <TEST_FUNC>.h
- to have the Halide/support directory in its include path, for static_image.h/image_io.h
*/

#ifndef TEST_FUNC
#error default_runner must be compiled with TEST_FUNC defined
#endif
#define TEST_HEADER TEST_FUNC.h

// Utilities to paste a macro as a string constant in another macro.
// via: http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
#define str(s) xstr(s)
#define xstr(s) #s

extern "C" {
#include str(TEST_HEADER)
}
#include <static_image.h>
#include <image_io.h>

#include <sys/time.h>

#include <string>
using std::string;

static const string usage = "Usage:\n\
\trunner <test iterations> <input_image.png> [reference_output.png] [w|-1] [h|-1] [channels|-1] [save_output.png]";

template<class T>
bool images_equal(Image<T> &a, Image<T> &b, T eps) {
    if (a.width() != b.width() || a.height() != b.height() || a.channels() != b.channels()) {
        return false;
    }
    for (int c = 0; c < a.channels(); c++) {
        for (int y = 0; y < a.height(); y++) {
            for (int x = 0; x < a.width(); x++) {
                T ac = a(x,y,c);
                T bc = b(x,y,c);
                T delta = ac > bc ? ac - bc: bc - ac;
                if (delta > eps) { return false; }
            }
        }
    }
    return true;
}

int main(int argc, char const *argv[])
{
    if (argc < 3) {
        fprintf(stderr, "%s\n", usage.c_str());
        return -1;
    }

    int test_iterations = atoi(argv[1]);

    timeval t1, t2;
    unsigned int t;
    gettimeofday(&t1, NULL);
    Image<TEST_IN_T> input = load<TEST_IN_T>(argv[2]);
    gettimeofday(&t2, NULL);
    t = (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec);
    printf("load time input: %.4f secs\n", t/(1000.0*1000.0));
    int w        = argc > 4 ? atoi(argv[4]): -1;
    int h        = argc > 5 ? atoi(argv[5]): -1;
    int channels = argc > 6 ? atoi(argv[6]): -1;
    char const *save_output = argc > 7 ? argv[7]: NULL;

    if (w < 0) { w = input.width(); }
    if (h < 0) { h = input.height(); }
    if (channels < 0) { channels = input.channels(); }

    Image<TEST_OUT_T> output(w, h, channels);
    Image<TEST_OUT_T> ref_output(1,1,1);
    bool has_ref = false;
    if (argc > 3 && strcmp(argv[3], "") != 0) {
        gettimeofday(&t1, NULL);
        ref_output = load<TEST_OUT_T>(argv[3]);
        gettimeofday(&t2, NULL);
        t = (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec);
        printf("load time output: %.4f secs\n", t/(1000.0*1000.0));
        has_ref = true;
    }

    // Timing code
    unsigned int bestT = 0xffffffff;
    for (int i = 0; i < test_iterations; i++) {
        gettimeofday(&t1, NULL);
        TEST_FUNC(input, output);
        gettimeofday(&t2, NULL);
        t = (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec);
        if (t < bestT) bestT = t;
    }

    // Saving large PNGs is expensive. Only do it if enabled.
    if (save_output != NULL && strcmp(save_output, "") != 0) {
        save(output, save_output);
    }

    if (has_ref) {
        if (!images_equal<TEST_OUT_T>(ref_output, output, 0.01)) {
            printf("RUN_CHECK_FAIL\n");
            exit(1);
        }
    }
    printf("Success %f\n", bestT/1000000.0);

    return 0;
}
<|endoftext|>


<commit_before>/*! \file optional.hpp
    \brief Support for std::optional
    \ingroup STLSupport */
/*
  Copyright (c) 2017, Juan Pedro Bolivar Puente
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
      * Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
      * Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
      * Neither the name of cereal nor the
        names of its contributors may be used to endorse or promote products
        derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CEREAL_TYPES_STD_OPTIONAL_
#define CEREAL_TYPES_STD_OPTIONAL_

#include "cereal/cereal.hpp"
#include <optional>

namespace cereal {
  //! Saving for std::optional
  template <class Archive, typename T> inline
  void CEREAL_SAVE_FUNCTION_NAME(Archive& ar, const std::optional<T>& optional)
  {
    if(optional) {
      ar(CEREAL_NVP_("nullopt", true));
    } else {
      ar(CEREAL_NVP_("nullopt", false),
         CEREAL_NVP_("value", *optional));
    }
  }

  //! Loading for std::optional
  template <class Archive, typename T> inline
  void CEREAL_LOAD_FUNCTION_NAME(Archive& ar, std::optional<T>& optional)
  {
    bool nullopt;
    ar(CEREAL_NVP_("nullopt", nullopt));

    if (nullopt) {
      optional = std::nullopt;
    } else {
      T value;
      ar(CEREAL_NVP_("value", value));
      optional = std::move(value);
    }
  }
} // namespace cereal

#endif // CEREAL_TYPES_STD_OPTIONAL_
<commit_msg>rename value to data<commit_after>/*! \file optional.hpp
    \brief Support for std::optional
    \ingroup STLSupport */
/*
  Copyright (c) 2017, Juan Pedro Bolivar Puente
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
      * Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
      * Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
      * Neither the name of cereal nor the
        names of its contributors may be used to endorse or promote products
        derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CEREAL_TYPES_STD_OPTIONAL_
#define CEREAL_TYPES_STD_OPTIONAL_

#include "cereal/cereal.hpp"
#include <optional>

namespace cereal {
  //! Saving for std::optional
  template <class Archive, typename T> inline
  void CEREAL_SAVE_FUNCTION_NAME(Archive& ar, const std::optional<T>& optional)
  {
    if(optional) {
      ar(CEREAL_NVP_("nullopt", true));
    } else {
      ar(CEREAL_NVP_("nullopt", false),
         CEREAL_NVP_("data", *optional));
    }
  }

  //! Loading for std::optional
  template <class Archive, typename T> inline
  void CEREAL_LOAD_FUNCTION_NAME(Archive& ar, std::optional<T>& optional)
  {
    bool nullopt;
    ar(CEREAL_NVP_("nullopt", nullopt));

    if (nullopt) {
      optional = std::nullopt;
    } else {
      T value;
      ar(CEREAL_NVP_("data", value));
      optional = std::move(value);
    }
  }
} // namespace cereal

#endif // CEREAL_TYPES_STD_OPTIONAL_
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (C) 2014 PX4 Development Team. All rights reserved.
 *   Author: Pavel Kirienko <pavel.kirienko@gmail.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

#include "esc_controller.hpp"
#include <uavcan/equipment/esc/RawCommand.hpp>
#include <uavcan/equipment/esc/RPMCommand.hpp>
#include <uavcan/equipment/esc/Status.hpp>
#include <config/config.h>
#include <motor/motor.h>
#include <limits>

namespace uavcan_node
{
namespace
{

uavcan::Publisher<uavcan::equipment::esc::Status>* pub_status;

unsigned self_index = 0;

CONFIG_PARAM_INT("uavcan_esc_index", 0,   0,  15)

void cb_raw_command(const uavcan::ReceivedDataStructure<uavcan::equipment::esc::RawCommand>& msg)
{
	(void)msg;
}

void cb_rpm_command(const uavcan::ReceivedDataStructure<uavcan::equipment::esc::RPMCommand>& msg)
{
	(void)msg;
}

void cb_10Hz(const uavcan::TimerEvent& event)
{
	uavcan::equipment::esc::Status msg;

	msg.index = self_index;
	msg.rpm = motor_get_rpm();
	motor_get_input_voltage_current(&msg.voltage, &msg.current);
	msg.temperature = std::numeric_limits<float>::quiet_NaN();
	msg.power_rate_pct = static_cast<unsigned>(motor_get_duty_cycle() * 100 + 0.5F);
	msg.error_count = motor_get_zc_failures_since_start();

	if (motor_is_idle()) {
		// Lower the publish rate to 1Hz if the motor is not running
		static uavcan::MonotonicTime prev_pub_ts;
		if ((event.scheduled_time - prev_pub_ts).toMSec() >= 990) {
			prev_pub_ts = event.scheduled_time;
			pub_status->broadcast(msg);
		}
	} else {
		pub_status->broadcast(msg);
	}
}

}

int init_esc_controller(uavcan::INode& node)
{
	static uavcan::Subscriber<uavcan::equipment::esc::RawCommand> sub_raw_command(node);
	static uavcan::Subscriber<uavcan::equipment::esc::RPMCommand> sub_rpm_command(node);
	static uavcan::Timer timer_10hz(node);

	self_index = config_get("uavcan_esc_index");

	int res = 0;

	res = sub_raw_command.start(cb_raw_command);
	if (res != 0) {
		return res;
	}

	res = sub_rpm_command.start(cb_rpm_command);
	if (res != 0) {
		return res;
	}

	pub_status = new uavcan::Publisher<uavcan::equipment::esc::Status>(node);
	res = pub_status->init();
	if (res != 0) {
		return res;
	}

	timer_10hz.setCallback(&cb_10Hz);
	timer_10hz.startPeriodic(uavcan::MonotonicDuration::fromMSec(100));

	return 0;
}

}
<commit_msg>Catching up with uavcan<commit_after>/****************************************************************************
 *
 *   Copyright (C) 2014 PX4 Development Team. All rights reserved.
 *   Author: Pavel Kirienko <pavel.kirienko@gmail.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

#include "esc_controller.hpp"
#include <uavcan/equipment/esc/RawCommand.hpp>
#include <uavcan/equipment/esc/RPMCommand.hpp>
#include <uavcan/equipment/esc/Status.hpp>
#include <config/config.h>
#include <motor/motor.h>
#include <limits>

namespace uavcan_node
{
namespace
{

uavcan::Publisher<uavcan::equipment::esc::Status>* pub_status;

unsigned self_index = 0;

CONFIG_PARAM_INT("uavcan_esc_index", 0,   0,  15)

void cb_raw_command(const uavcan::ReceivedDataStructure<uavcan::equipment::esc::RawCommand>& msg)
{
	(void)msg;
}

void cb_rpm_command(const uavcan::ReceivedDataStructure<uavcan::equipment::esc::RPMCommand>& msg)
{
	(void)msg;
}

void cb_10Hz(const uavcan::TimerEvent& event)
{
	uavcan::equipment::esc::Status msg;

	msg.index = self_index;
	msg.rpm = motor_get_rpm();
	motor_get_input_voltage_current(&msg.voltage, &msg.current);
	msg.temperature = std::numeric_limits<float>::quiet_NaN();
	msg.power_rating_pct = static_cast<unsigned>(motor_get_duty_cycle() * 100 + 0.5F);
	msg.error_count = motor_get_zc_failures_since_start();

	if (motor_is_idle()) {
		// Lower the publish rate to 1Hz if the motor is not running
		static uavcan::MonotonicTime prev_pub_ts;
		if ((event.scheduled_time - prev_pub_ts).toMSec() >= 990) {
			prev_pub_ts = event.scheduled_time;
			pub_status->broadcast(msg);
		}
	} else {
		pub_status->broadcast(msg);
	}
}

}

int init_esc_controller(uavcan::INode& node)
{
	static uavcan::Subscriber<uavcan::equipment::esc::RawCommand> sub_raw_command(node);
	static uavcan::Subscriber<uavcan::equipment::esc::RPMCommand> sub_rpm_command(node);
	static uavcan::Timer timer_10hz(node);

	self_index = config_get("uavcan_esc_index");

	int res = 0;

	res = sub_raw_command.start(cb_raw_command);
	if (res != 0) {
		return res;
	}

	res = sub_rpm_command.start(cb_rpm_command);
	if (res != 0) {
		return res;
	}

	pub_status = new uavcan::Publisher<uavcan::equipment::esc::Status>(node);
	res = pub_status->init();
	if (res != 0) {
		return res;
	}

	timer_10hz.setCallback(&cb_10Hz);
	timer_10hz.startPeriodic(uavcan::MonotonicDuration::fromMSec(100));

	return 0;
}

}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee++ — Transaction
 *
 * This file defines (Const)Transaction, a wrapper for ib_tx_t.
 *
 * @remark Developers should be familiar with @ref ironbeepp to understand
 * aspects of this code, e.g., the public/non-virtual inheritance.
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __IBPP__TRANSACTION__
#define __IBPP__TRANSACTION__

#include <ironbeepp/common_semantics.hpp>

#include <ironbee/engine.h>

#include <boost/date_time/posix_time/ptime.hpp>

#include <ostream>

namespace IronBee {

class Engine;
class Context;
class MemoryPool;
class Transaction;
class Connection;

/**
 * Const Transaction; equivalent to a const pointer to ib_tx_t.
 *
 * Provides operators ==, !=, <, >, <=, >= and evaluation as a boolean for
 * singularity via CommonSemantics.
 *
 * See Transaction for discussion of Transaction
 *
 * @sa Transaction
 * @sa ironbeepp
 * @sa ib_tx_t
 * @nosubgrouping
 **/
class ConstTransaction :
    public CommonSemantics<ConstTransaction>
{
public:
    //! C Type.
    typedef const ib_tx_t* ib_type;

    /**
     * Construct singular ConstTransaction.
     *
     * All behavior of a singular ConstTransaction is undefined except for
     * assignment, copying, comparison, and evaluate-as-bool.
     **/
    ConstTransaction();

    /**
     * @name C Interoperability
     * Methods to access underlying C types.
     **/
    ///@{

    //! const ib_tx_t accessor.
    // Intentionally inlined.
    ib_type ib() const
    {
        return m_ib;
    }

    //! Construct Transaction from ib_tx_t.
    explicit
    ConstTransaction(ib_type ib_transaction);

    ///@}

    //! Associated engine.
    Engine engine() const;

    //! Memory pool used.
    MemoryPool memory_pool() const;

    //! Identifier.
    const char* id() const;

    //! Associated connection.
    Connection connection() const;

    //! Associated connection.
    Context context() const;

    /**
     * @name Timestamps
     * Timestamps.
     **/
    ///@{

    //! Start of transaction.
    boost::posix_time::ptime started() const;

    //! Start of request.
    boost::posix_time::ptime request_started() const;

    //! Start of request headers.
    boost::posix_time::ptime request_headers() const;

    //! Start of request body.
    boost::posix_time::ptime request_body() const;

    //! Finish of request.
    boost::posix_time::ptime request_finished() const;

    //! Start of response.
    boost::posix_time::ptime response_started() const;

    //! Start of response headers.
    boost::posix_time::ptime response_headers() const;

    //! Start of response body.
    boost::posix_time::ptime response_body() const;

    //! Finish of response.
    boost::posix_time::ptime response_finished() const;

    //! Start of post processing.
    boost::posix_time::ptime postprocess() const;

    //! Start of event logging.
    boost::posix_time::ptime logtime() const;

    //! Finish of transaction.
    boost::posix_time::ptime finished() const;
    ///@}

    //! Next transaction in current sequence.
    Transaction next() const;

    //! Hostname used in request.
    const char* hostname() const;

    //! Effective remote IP string.
    const char* effective_remote_ip_string() const;

    //! Path used in request.
    const char* path() const;

    /**
     * @defgroup Flags
     * Transaction Flags
     *
     * The masks for the flags are defined by the flags_e enum.  All flags
     * as a set of bits can be accessed via flags().  Individual flags can be
     * checked either via flags() @c & @c flag_X or via @c is_X().
     **/
    ///@{

    //! Possible flags.  Treat as bit masks.
    enum flags_e {
        flag_none                  = IB_TX_FNONE,
        flag_error                 = IB_TX_FERROR,
        flag_pipelined             = IB_TX_FPIPELINED,
        flag_seen_data_in          = IB_TX_FSEENDATAIN,
        flag_seen_data_out         = IB_TX_FSEENDATAOUT,
        flag_request_started       = IB_TX_FREQ_STARTED,
        flag_request_seen_headers  = IB_TX_FREQ_SEENHEADERS,
        flag_request_no_body       = IB_TX_FREQ_NOBODY,
        flag_request_seen_body     = IB_TX_FREQ_SEENBODY,
        flag_request_finished      = IB_TX_FREQ_FINISHED,
        flag_response_started      = IB_TX_FRES_STARTED,
        flag_response_seen_headers = IB_TX_FRES_SEENHEADERS,
        flag_response_seen_body    = IB_TX_FRES_SEENBODY,
        flag_response_finished     = IB_TX_FRES_FINISHED,
        flag_suspicious            = IB_TX_FSUSPICIOUS
    };

    //! All flags.
    uint32_t flags() const;

    //! flags() & flag_none
    bool is_none() const
    {
        return flags() & flag_none;
    }

    //! flags() & flag_error
    bool is_error() const
    {
        return flags() & flag_error;
    }

    //! flags() & flag_pipelined
    bool is_pipelined() const
    {
        return flags() & flag_pipelined;
    }

    //! flags() & flag_seen_data_in
    bool is_seen_data_in() const
    {
        return flags() & flag_seen_data_in;
    }

    //! flags() & flag_seen_data_out
    bool is_seen_data_out() const
    {
        return flags() & flag_seen_data_out;
    }

    //! flags() & flag_request_started
    bool is_request_started() const
    {
        return flags() & flag_request_started;
    }

    //! flags() & flag_request_seen_headers
    bool is_request_seen_headers() const
    {
        return flags() & flag_request_seen_headers;
    }

    //! flags() & flag_request_no_body
    bool is_request_no_body() const
    {
        return flags() & flag_request_no_body;
    }

    //! flags() & flag_request_seen_body
    bool is_request_seen_body() const
    {
        return flags() & flag_request_seen_body;
    }

    //! flags() & flag_request_finished
    bool is_request_finished() const
    {
        return flags() & flag_request_finished;
    }

    //! flags() & flag_response_started
    bool is_response_started() const
    {
        return flags() & flag_response_started;
    }

    //! flags() & flag_response_seen_headers
    bool is_response_seen_headers() const
    {
        return flags() & flag_response_seen_headers;
    }

    //! flags() & flag_response_seen_body
    bool is_response_seen_body() const
    {
        return flags() & flag_response_seen_body;
    }

    //! flags() & flag_response_finished
    bool is_response_finished() const
    {
        return flags() & flag_response_finished;
    }

    //! flags() & flag_suspicious
    bool is_suspicious() const
    {
        return flags() & flag_suspicious;
    }

    ///@}

private:
    ib_type m_ib;
};

/**
 * Transaction; equivalent to a pointer to ib_tx_t.
 *
 * Transaction can be treated as ConstTransaction.  See @ref ironbeepp for
 * details on IronBee++ object semantics.
 *
 * A transaction is a request/response pair within a connection.  Current
 * C++ support is limited.
 *
 * This class adds no functionality to ConstTransaction beyond providing a
 * non-const @c ib_tx_t* via ib().
 *
 * @sa ConstTransaction
 * @sa ironbeepp
 * @sa ib_tx_t
 * @nosubgrouping
 **/
class Transaction :
    public ConstTransaction
{
public:
    //! C Type.
    typedef ib_tx_t* ib_type;

    /**
     * Remove the constness of a ConstTransaction.
     *
     * @warning This is as dangerous as a @c const_cast, use carefully.
     *
     * @param[in] transaction ConstTransaction to remove const from.
     * @returns Transaction pointing to same underlying transaction as
     *          @a transaction.
     **/
    static Transaction remove_const(ConstTransaction transaction);

    /**
     * Construct singular Transaction.
     *
     * All behavior of a singular Transaction is undefined except for
     * assignment, copying, comparison, and evaluate-as-bool.
     **/
    Transaction();

    /**
     * @name C Interoperability
     * Methods to access underlying C types.
     **/
    ///@{

    //! ib_tx_t accessor.
    ib_type ib() const
    {
        return m_ib;
    }

    //! Construct Transaction from ib_tx_t.
    explicit
    Transaction(ib_type ib_transaction);

    ///@}

private:
    ib_type m_ib;
};

/**
 * Output operator for Transaction.
 *
 * Output IronBee::Transaction[@e value] where @e value is the id.
 *
 * @param[in] o Ostream to output to.
 * @param[in] transaction Transaction to output.
 * @return @a o
 **/
std::ostream& operator<<(
    std::ostream&           o,
    const ConstTransaction& transaction
);

} // IronBee

#endif
<commit_msg>IronBee++/Transaction: Fix potential clang warning.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee++ — Transaction
 *
 * This file defines (Const)Transaction, a wrapper for ib_tx_t.
 *
 * @remark Developers should be familiar with @ref ironbeepp to understand
 * aspects of this code, e.g., the public/non-virtual inheritance.
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __IBPP__TRANSACTION__
#define __IBPP__TRANSACTION__

#include <ironbeepp/common_semantics.hpp>

#include <ironbee/engine.h>

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdelete-non-virtual-dtor"
#endif
#include <boost/date_time/posix_time/ptime.hpp>
#ifdef __clang__
#pragma clang diagnostic pop
#endif

#include <ostream>

namespace IronBee {

class Engine;
class Context;
class MemoryPool;
class Transaction;
class Connection;

/**
 * Const Transaction; equivalent to a const pointer to ib_tx_t.
 *
 * Provides operators ==, !=, <, >, <=, >= and evaluation as a boolean for
 * singularity via CommonSemantics.
 *
 * See Transaction for discussion of Transaction
 *
 * @sa Transaction
 * @sa ironbeepp
 * @sa ib_tx_t
 * @nosubgrouping
 **/
class ConstTransaction :
    public CommonSemantics<ConstTransaction>
{
public:
    //! C Type.
    typedef const ib_tx_t* ib_type;

    /**
     * Construct singular ConstTransaction.
     *
     * All behavior of a singular ConstTransaction is undefined except for
     * assignment, copying, comparison, and evaluate-as-bool.
     **/
    ConstTransaction();

    /**
     * @name C Interoperability
     * Methods to access underlying C types.
     **/
    ///@{

    //! const ib_tx_t accessor.
    // Intentionally inlined.
    ib_type ib() const
    {
        return m_ib;
    }

    //! Construct Transaction from ib_tx_t.
    explicit
    ConstTransaction(ib_type ib_transaction);

    ///@}

    //! Associated engine.
    Engine engine() const;

    //! Memory pool used.
    MemoryPool memory_pool() const;

    //! Identifier.
    const char* id() const;

    //! Associated connection.
    Connection connection() const;

    //! Associated connection.
    Context context() const;

    /**
     * @name Timestamps
     * Timestamps.
     **/
    ///@{

    //! Start of transaction.
    boost::posix_time::ptime started() const;

    //! Start of request.
    boost::posix_time::ptime request_started() const;

    //! Start of request headers.
    boost::posix_time::ptime request_headers() const;

    //! Start of request body.
    boost::posix_time::ptime request_body() const;

    //! Finish of request.
    boost::posix_time::ptime request_finished() const;

    //! Start of response.
    boost::posix_time::ptime response_started() const;

    //! Start of response headers.
    boost::posix_time::ptime response_headers() const;

    //! Start of response body.
    boost::posix_time::ptime response_body() const;

    //! Finish of response.
    boost::posix_time::ptime response_finished() const;

    //! Start of post processing.
    boost::posix_time::ptime postprocess() const;

    //! Start of event logging.
    boost::posix_time::ptime logtime() const;

    //! Finish of transaction.
    boost::posix_time::ptime finished() const;
    ///@}

    //! Next transaction in current sequence.
    Transaction next() const;

    //! Hostname used in request.
    const char* hostname() const;

    //! Effective remote IP string.
    const char* effective_remote_ip_string() const;

    //! Path used in request.
    const char* path() const;

    /**
     * @defgroup Flags
     * Transaction Flags
     *
     * The masks for the flags are defined by the flags_e enum.  All flags
     * as a set of bits can be accessed via flags().  Individual flags can be
     * checked either via flags() @c & @c flag_X or via @c is_X().
     **/
    ///@{

    //! Possible flags.  Treat as bit masks.
    enum flags_e {
        flag_none                  = IB_TX_FNONE,
        flag_error                 = IB_TX_FERROR,
        flag_pipelined             = IB_TX_FPIPELINED,
        flag_seen_data_in          = IB_TX_FSEENDATAIN,
        flag_seen_data_out         = IB_TX_FSEENDATAOUT,
        flag_request_started       = IB_TX_FREQ_STARTED,
        flag_request_seen_headers  = IB_TX_FREQ_SEENHEADERS,
        flag_request_no_body       = IB_TX_FREQ_NOBODY,
        flag_request_seen_body     = IB_TX_FREQ_SEENBODY,
        flag_request_finished      = IB_TX_FREQ_FINISHED,
        flag_response_started      = IB_TX_FRES_STARTED,
        flag_response_seen_headers = IB_TX_FRES_SEENHEADERS,
        flag_response_seen_body    = IB_TX_FRES_SEENBODY,
        flag_response_finished     = IB_TX_FRES_FINISHED,
        flag_suspicious            = IB_TX_FSUSPICIOUS
    };

    //! All flags.
    uint32_t flags() const;

    //! flags() & flag_none
    bool is_none() const
    {
        return flags() & flag_none;
    }

    //! flags() & flag_error
    bool is_error() const
    {
        return flags() & flag_error;
    }

    //! flags() & flag_pipelined
    bool is_pipelined() const
    {
        return flags() & flag_pipelined;
    }

    //! flags() & flag_seen_data_in
    bool is_seen_data_in() const
    {
        return flags() & flag_seen_data_in;
    }

    //! flags() & flag_seen_data_out
    bool is_seen_data_out() const
    {
        return flags() & flag_seen_data_out;
    }

    //! flags() & flag_request_started
    bool is_request_started() const
    {
        return flags() & flag_request_started;
    }

    //! flags() & flag_request_seen_headers
    bool is_request_seen_headers() const
    {
        return flags() & flag_request_seen_headers;
    }

    //! flags() & flag_request_no_body
    bool is_request_no_body() const
    {
        return flags() & flag_request_no_body;
    }

    //! flags() & flag_request_seen_body
    bool is_request_seen_body() const
    {
        return flags() & flag_request_seen_body;
    }

    //! flags() & flag_request_finished
    bool is_request_finished() const
    {
        return flags() & flag_request_finished;
    }

    //! flags() & flag_response_started
    bool is_response_started() const
    {
        return flags() & flag_response_started;
    }

    //! flags() & flag_response_seen_headers
    bool is_response_seen_headers() const
    {
        return flags() & flag_response_seen_headers;
    }

    //! flags() & flag_response_seen_body
    bool is_response_seen_body() const
    {
        return flags() & flag_response_seen_body;
    }

    //! flags() & flag_response_finished
    bool is_response_finished() const
    {
        return flags() & flag_response_finished;
    }

    //! flags() & flag_suspicious
    bool is_suspicious() const
    {
        return flags() & flag_suspicious;
    }

    ///@}

private:
    ib_type m_ib;
};

/**
 * Transaction; equivalent to a pointer to ib_tx_t.
 *
 * Transaction can be treated as ConstTransaction.  See @ref ironbeepp for
 * details on IronBee++ object semantics.
 *
 * A transaction is a request/response pair within a connection.  Current
 * C++ support is limited.
 *
 * This class adds no functionality to ConstTransaction beyond providing a
 * non-const @c ib_tx_t* via ib().
 *
 * @sa ConstTransaction
 * @sa ironbeepp
 * @sa ib_tx_t
 * @nosubgrouping
 **/
class Transaction :
    public ConstTransaction
{
public:
    //! C Type.
    typedef ib_tx_t* ib_type;

    /**
     * Remove the constness of a ConstTransaction.
     *
     * @warning This is as dangerous as a @c const_cast, use carefully.
     *
     * @param[in] transaction ConstTransaction to remove const from.
     * @returns Transaction pointing to same underlying transaction as
     *          @a transaction.
     **/
    static Transaction remove_const(ConstTransaction transaction);

    /**
     * Construct singular Transaction.
     *
     * All behavior of a singular Transaction is undefined except for
     * assignment, copying, comparison, and evaluate-as-bool.
     **/
    Transaction();

    /**
     * @name C Interoperability
     * Methods to access underlying C types.
     **/
    ///@{

    //! ib_tx_t accessor.
    ib_type ib() const
    {
        return m_ib;
    }

    //! Construct Transaction from ib_tx_t.
    explicit
    Transaction(ib_type ib_transaction);

    ///@}

private:
    ib_type m_ib;
};

/**
 * Output operator for Transaction.
 *
 * Output IronBee::Transaction[@e value] where @e value is the id.
 *
 * @param[in] o Ostream to output to.
 * @param[in] transaction Transaction to output.
 * @return @a o
 **/
std::ostream& operator<<(
    std::ostream&           o,
    const ConstTransaction& transaction
);

} // IronBee

#endif
<|endoftext|>