<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cf_service.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2005-11-02 12:46:34 $
 *
 *  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
 *
 ************************************************************************/
#include "osl/mutex.hxx"
#include "cppuhelper/implementationentry.hxx"
#include "cppuhelper/factory.hxx"
#include "cppuhelper/implbase3.hxx"
#include "vcl/configsettings.hxx"
#include "com/sun/star/uno/XComponentContext.hpp"
#include "com/sun/star/lang/XServiceInfo.hpp"
#include "com/sun/star/lang/XSingleComponentFactory.hpp"
#include "com/sun/star/container/XContentEnumerationAccess.hpp"
#include "com/sun/star/container/XNameAccess.hpp"
#include "com/sun/star/beans/PropertyValue.hpp"

#include <vector>
#include <algorithm>

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
#define ARLEN(x) (sizeof (x) / sizeof *(x))

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using ::rtl::OUString;

namespace {

OUString SAL_CALL getImplName()
{
    return OUSTR("com.sun.star.comp.rendering.CanvasFactory");
}

Sequence<OUString> SAL_CALL getSuppServices()
{
    OUString name = OUSTR("com.sun.star.rendering.CanvasFactory");
    return Sequence<OUString>(&name, 1);
}

//==============================================================================
class CanvasFactory
    : public ::cppu::WeakImplHelper3< lang::XServiceInfo,
                                      lang::XMultiComponentFactory,
                                      lang::XMultiServiceFactory >
{
    ::osl::Mutex m_mutex;
    Reference<XComponentContext> m_xContext;
    Sequence<OUString> m_services;
    OUString m_serviceName;
    Reference<lang::XSingleComponentFactory> m_xFactory;

    Reference<XInterface> use(
        Reference<lang::XSingleComponentFactory> const & xFactory,
        Sequence<Any> const & args,
        Reference<XComponentContext> const & xContext );
    Reference<XInterface> lookupAndUse(
        OUString const & serviceName, Sequence<Any> const & args,
        Reference<XComponentContext> const & xContext );

public:
    virtual ~CanvasFactory();
    CanvasFactory( Reference<XComponentContext> const & xContext );

    // XServiceInfo
    virtual OUString SAL_CALL getImplementationName() throw (RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName )
        throw (RuntimeException);
    virtual Sequence<OUString> SAL_CALL getSupportedServiceNames()
        throw (RuntimeException);

    // XMultiComponentFactory
    virtual Sequence<OUString> SAL_CALL getAvailableServiceNames()
        throw (RuntimeException);
    virtual Reference<XInterface> SAL_CALL createInstanceWithContext(
        OUString const & name,
        Reference<XComponentContext> const & xContext ) throw (Exception);
    virtual Reference<XInterface> SAL_CALL
    createInstanceWithArgumentsAndContext(
        OUString const & name,
        Sequence<Any> const & args,
        Reference<XComponentContext> const & xContext ) throw (Exception);

    // XMultiServiceFactory
    virtual Reference<XInterface> SAL_CALL createInstance(
        OUString const & name )
        throw (Exception);
    virtual Reference<XInterface> SAL_CALL createInstanceWithArguments(
        OUString const & name, Sequence<Any> const & args )
        throw (Exception);
//     virtual Sequence<OUString> SAL_CALL getAvailableServiceNames()
//         throw (RuntimeException);
};

CanvasFactory::CanvasFactory(
    Reference<XComponentContext> const & xContext )
    : m_xContext(xContext)
{
    ::rtl::OUString preferredServices;

    try
    {
        // read out configuration for preferred services:
        Reference<lang::XMultiServiceFactory> xConfigProvider(
            m_xContext->getServiceManager()->createInstanceWithContext(
                OUSTR("com.sun.star.configuration.ConfigurationProvider"),
                m_xContext ), UNO_QUERY_THROW );

        Any propValue(
            makeAny( beans::PropertyValue(
                         OUSTR("nodepath"), -1,
                         makeAny( OUSTR("/org.openoffice.VCL/Settings/Canvas") ),
                         beans::PropertyState_DIRECT_VALUE ) ) );

        Reference<container::XNameAccess> xNameAccess(
            xConfigProvider->createInstanceWithArguments(
                OUSTR("com.sun.star.configuration.ConfigurationAccess"),
                Sequence<Any>( &propValue, 1 ) ), UNO_QUERY );

        if (xNameAccess.is())
            xNameAccess->getByName( OUSTR("PreferredServices") ) >>= preferredServices;
    }
    catch (RuntimeException &) {
        throw;
    }
    catch (Exception & exc) {
        (void) exc;
    }

    ::std::vector< ::rtl::OUString > services;
    sal_Int32 tokenPos = 0;
    do
    {
        ::rtl::OUString oneService = preferredServices.getToken( 0, ';', tokenPos );
        if ( oneService.getLength() )
            services.push_back( oneService );
    }
    while ( tokenPos > 0 );
    m_services.realloc( services.size() );
    ::std::copy( services.begin(), services.end(), m_services.getArray() );

    // append the usual preferred ones:
    sal_Int32 pos = m_services.getLength();
#if defined WNT
    m_services.realloc( pos + 4 );
    m_services[ pos++ ] = OUSTR("com.sun.star.rendering.DXCanvas");
    m_services[ pos++ ] = OUSTR("com.sun.star.rendering.GLCanvas");
#else
    m_services.realloc( pos + 3 );
    m_services[ pos++ ] = OUSTR("com.sun.star.rendering.GLCanvas");
#endif
    m_services[ pos++ ] = OUSTR("com.sun.star.rendering.JavaCanvas");
    m_services[ pos   ] = OUSTR("com.sun.star.rendering.VCLCanvas");
}

CanvasFactory::~CanvasFactory()
{
}

//------------------------------------------------------------------------------
Reference<XInterface> create( Reference<XComponentContext> const & xContext )
{
    return static_cast< ::cppu::OWeakObject * >(
        new CanvasFactory( xContext ) );
}

// XServiceInfo
//______________________________________________________________________________
OUString CanvasFactory::getImplementationName() throw (RuntimeException)
{
    return getImplName();
}

//______________________________________________________________________________
sal_Bool CanvasFactory::supportsService( OUString const & serviceName )
    throw (RuntimeException)
{
    return serviceName.equals(getSuppServices()[0]);
}

//______________________________________________________________________________
Sequence<OUString> CanvasFactory::getSupportedServiceNames()
    throw (RuntimeException)
{
    return getSuppServices();
}

// XMultiComponentFactory
//______________________________________________________________________________
Sequence<OUString> CanvasFactory::getAvailableServiceNames()
    throw (RuntimeException)
{
    return m_services;
}

//______________________________________________________________________________
Reference<XInterface> CanvasFactory::createInstanceWithContext(
    OUString const & name, Reference<XComponentContext> const & xContext )
    throw (Exception)
{
    return createInstanceWithArgumentsAndContext(
        name, Sequence<Any>(), xContext );
}

//______________________________________________________________________________
Reference<XInterface> CanvasFactory::use(
    Reference<lang::XSingleComponentFactory> const & xFactory,
    Sequence<Any> const & args, Reference<XComponentContext> const & xContext )
{
    try {
        return xFactory->createInstanceWithArgumentsAndContext(args, xContext);
    }
    catch (RuntimeException &) {
        throw;
    }
    catch (Exception &) {
        return Reference<XInterface>();
    }
}

//______________________________________________________________________________
Reference<XInterface> CanvasFactory::lookupAndUse(
    OUString const & serviceName, Sequence<Any> const & args,
    Reference<XComponentContext> const & xContext )
{
    {
        // try to reuse:
        ::osl::ClearableMutexGuard guard(m_mutex);
        if (m_serviceName.equals(serviceName)) {
            Reference<lang::XSingleComponentFactory> xFac(m_xFactory);
            guard.clear();
            Reference<XInterface> xCanvas( use( xFac, args, xContext ) );
            if (xCanvas.is())
                return xCanvas;
        }
    }

    Reference<container::XContentEnumerationAccess> xEnumAccess(
        // use service manager of factory:
        m_xContext->getServiceManager(), UNO_QUERY_THROW );
    Reference<container::XEnumeration> xEnum(
        xEnumAccess->createContentEnumeration( serviceName ) );
    if (xEnum.is()) {
        while (xEnum->hasMoreElements()) {
            Reference<lang::XSingleComponentFactory> xFactory(
                xEnum->nextElement(), UNO_QUERY );
            OSL_ASSERT( xFactory.is() );
            if (xFactory.is()) {
                Reference<XInterface> xCanvas(
                    use( xFactory, args, xContext ) );
                if (xCanvas.is()) {
                    ::osl::MutexGuard guard(m_mutex);
                    // init for reuse:
                    m_xFactory.set(xFactory);
                    m_serviceName = serviceName;
                    return xCanvas;
                }
            }
        }
    }

    return Reference<XInterface>();
}

//______________________________________________________________________________
Reference<XInterface> CanvasFactory::createInstanceWithArgumentsAndContext(
    OUString const & preferredOne, Sequence<Any> const & args,
    Reference<XComponentContext> const & xContext ) throw (Exception)
{
    // preferred one overrides previously used one:
    if (preferredOne.getLength() > 0) {
        Reference<XInterface> xCanvas(
            lookupAndUse( preferredOne, args, xContext ) );
        if (xCanvas.is())
            return xCanvas;
    }

    {
        // try to reuse previously installed factory:
        ::osl::ClearableMutexGuard guard(m_mutex);
        if (m_xFactory.is()) {
            Reference<lang::XSingleComponentFactory> xFac(m_xFactory);
            guard.clear();
            Reference<XInterface> xCanvas( use( xFac, args, xContext ) );
            if (xCanvas.is())
                return xCanvas;
        }
    }

    // try configured ones:
    OUString const * pservices = m_services.getConstArray();
    sal_Int32 pos = 0, len = m_services.getLength();
    for ( ; pos < len; ++pos ) {
        Reference<XInterface> xCanvas(
            lookupAndUse( pservices[pos], args, xContext ) );
        if (xCanvas.is())
            return xCanvas;
    }

    OSL_ENSURE( 0, "### no canvas available!?" );
    return Reference<XInterface>();
}

// XMultiServiceFactory
//______________________________________________________________________________
Reference<XInterface> CanvasFactory::createInstance( OUString const & name )
    throw (Exception)
{
    return createInstanceWithArgumentsAndContext(
        name, Sequence<Any>(), m_xContext );
}

//______________________________________________________________________________
Reference<XInterface> CanvasFactory::createInstanceWithArguments(
    OUString const & name, Sequence<Any> const & args ) throw (Exception)
{
    return createInstanceWithArgumentsAndContext(
        name, args, m_xContext );
}

const ::cppu::ImplementationEntry s_entries [] = {
    {
        create,
        getImplName,
        getSuppServices,
        ::cppu::createSingleComponentFactory,
        0, 0
    },
    { 0, 0, 0, 0, 0, 0 }
};

} // anon namespace

extern "C" {

void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

sal_Bool SAL_CALL component_writeInfo(
    lang::XMultiServiceFactory * pServiceManager,
    registry::XRegistryKey * pRegistryKey )
{
    return ::cppu::component_writeInfoHelper(
        pServiceManager, pRegistryKey, s_entries );
}

void * SAL_CALL component_getFactory(
    sal_Char const * pImplName,
    lang::XMultiServiceFactory * pServiceManager,
    registry::XRegistryKey * pRegistryKey )
{
    return ::cppu::component_getFactoryHelper(
        pImplName, pServiceManager, pRegistryKey, s_entries );
}

}

<commit_msg>INTEGRATION: CWS cairocanvas (1.5.14); FILE MERGED 2005/11/04 14:26:03 thb 1.5.14.3: RESYNC: (1.5-1.7); FILE MERGED 2005/07/08 10:41:18 thb 1.5.14.2: #i51657# Reverted getenv() to osl function 2005/07/07 07:58:08 radekdoulik 1.5.14.1: Issue number:  51657 Submitted by:  radekdoulik Reviewed by:   radekdoulik initial import of cairo canvas code<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cf_service.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: kz $ $Date: 2006-02-28 10:40:38 $
 *
 *  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
 *
 ************************************************************************/
#include "osl/mutex.hxx"
#include "osl/process.h"
#include "cppuhelper/implementationentry.hxx"
#include "cppuhelper/factory.hxx"
#include "cppuhelper/implbase3.hxx"
#include "vcl/configsettings.hxx"
#include "com/sun/star/uno/XComponentContext.hpp"
#include "com/sun/star/lang/XServiceInfo.hpp"
#include "com/sun/star/lang/XSingleComponentFactory.hpp"
#include "com/sun/star/container/XContentEnumerationAccess.hpp"
#include "com/sun/star/container/XNameAccess.hpp"
#include "com/sun/star/beans/PropertyValue.hpp"

#include <vector>
#include <algorithm>

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
#define ARLEN(x) (sizeof (x) / sizeof *(x))

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using ::rtl::OUString;

namespace {

OUString SAL_CALL getImplName()
{
    return OUSTR("com.sun.star.comp.rendering.CanvasFactory");
}

Sequence<OUString> SAL_CALL getSuppServices()
{
    OUString name = OUSTR("com.sun.star.rendering.CanvasFactory");
    return Sequence<OUString>(&name, 1);
}

//==============================================================================
class CanvasFactory
    : public ::cppu::WeakImplHelper3< lang::XServiceInfo,
                                      lang::XMultiComponentFactory,
                                      lang::XMultiServiceFactory >
{
    ::osl::Mutex m_mutex;
    Reference<XComponentContext> m_xContext;
    Sequence<OUString> m_services;
    OUString m_serviceName;
    Reference<lang::XSingleComponentFactory> m_xFactory;

    Reference<XInterface> use(
        Reference<lang::XSingleComponentFactory> const & xFactory,
        Sequence<Any> const & args,
        Reference<XComponentContext> const & xContext );
    Reference<XInterface> lookupAndUse(
        OUString const & serviceName, Sequence<Any> const & args,
        Reference<XComponentContext> const & xContext );

public:
    virtual ~CanvasFactory();
    CanvasFactory( Reference<XComponentContext> const & xContext );

    // XServiceInfo
    virtual OUString SAL_CALL getImplementationName() throw (RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName )
        throw (RuntimeException);
    virtual Sequence<OUString> SAL_CALL getSupportedServiceNames()
        throw (RuntimeException);

    // XMultiComponentFactory
    virtual Sequence<OUString> SAL_CALL getAvailableServiceNames()
        throw (RuntimeException);
    virtual Reference<XInterface> SAL_CALL createInstanceWithContext(
        OUString const & name,
        Reference<XComponentContext> const & xContext ) throw (Exception);
    virtual Reference<XInterface> SAL_CALL
    createInstanceWithArgumentsAndContext(
        OUString const & name,
        Sequence<Any> const & args,
        Reference<XComponentContext> const & xContext ) throw (Exception);

    // XMultiServiceFactory
    virtual Reference<XInterface> SAL_CALL createInstance(
        OUString const & name )
        throw (Exception);
    virtual Reference<XInterface> SAL_CALL createInstanceWithArguments(
        OUString const & name, Sequence<Any> const & args )
        throw (Exception);
//     virtual Sequence<OUString> SAL_CALL getAvailableServiceNames()
//         throw (RuntimeException);
};

CanvasFactory::CanvasFactory(
    Reference<XComponentContext> const & xContext )
    : m_xContext(xContext)
{
    ::rtl::OUString preferredServices;

    try
    {
        // read out configuration for preferred services:
        Reference<lang::XMultiServiceFactory> xConfigProvider(
            m_xContext->getServiceManager()->createInstanceWithContext(
                OUSTR("com.sun.star.configuration.ConfigurationProvider"),
                m_xContext ), UNO_QUERY_THROW );

        Any propValue(
            makeAny( beans::PropertyValue(
                         OUSTR("nodepath"), -1,
                         makeAny( OUSTR("/org.openoffice.VCL/Settings/Canvas") ),
                         beans::PropertyState_DIRECT_VALUE ) ) );

        Reference<container::XNameAccess> xNameAccess(
            xConfigProvider->createInstanceWithArguments(
                OUSTR("com.sun.star.configuration.ConfigurationAccess"),
                Sequence<Any>( &propValue, 1 ) ), UNO_QUERY );

        if (xNameAccess.is())
            xNameAccess->getByName( OUSTR("PreferredServices") ) >>= preferredServices;
    }
    catch (RuntimeException &) {
        throw;
    }
    catch (Exception & exc) {
        (void) exc;
    }

    ::std::vector< ::rtl::OUString > services;
    sal_Int32 tokenPos = 0;
    do
    {
        ::rtl::OUString oneService = preferredServices.getToken( 0, ';', tokenPos );
        if ( oneService.getLength() )
            services.push_back( oneService );
    }
    while ( tokenPos > 0 );
    m_services.realloc( services.size() );
    ::std::copy( services.begin(), services.end(), m_services.getArray() );

    // append the usual preferred ones:
    sal_Int32 pos = m_services.getLength();
#if defined WNT
    m_services.realloc( pos + 5 );
    m_services[ pos++ ] = OUSTR("com.sun.star.rendering.DXCanvas");
    m_services[ pos++ ] = OUSTR("com.sun.star.rendering.GLCanvas");
#else
    m_services.realloc( pos + 4 );
    m_services[ pos++ ] = OUSTR("com.sun.star.rendering.GLCanvas");
#endif
    m_services[ pos++ ] = OUSTR("com.sun.star.rendering.CairoCanvas");
    m_services[ pos++ ] = OUSTR("com.sun.star.rendering.JavaCanvas");
    m_services[ pos   ] = OUSTR("com.sun.star.rendering.VCLCanvas");
}

CanvasFactory::~CanvasFactory()
{
}

//------------------------------------------------------------------------------
Reference<XInterface> create( Reference<XComponentContext> const & xContext )
{
    return static_cast< ::cppu::OWeakObject * >(
        new CanvasFactory( xContext ) );
}

// XServiceInfo
//______________________________________________________________________________
OUString CanvasFactory::getImplementationName() throw (RuntimeException)
{
    return getImplName();
}

//______________________________________________________________________________
sal_Bool CanvasFactory::supportsService( OUString const & serviceName )
    throw (RuntimeException)
{
    return serviceName.equals(getSuppServices()[0]);
}

//______________________________________________________________________________
Sequence<OUString> CanvasFactory::getSupportedServiceNames()
    throw (RuntimeException)
{
    return getSuppServices();
}

// XMultiComponentFactory
//______________________________________________________________________________
Sequence<OUString> CanvasFactory::getAvailableServiceNames()
    throw (RuntimeException)
{
    return m_services;
}

//______________________________________________________________________________
Reference<XInterface> CanvasFactory::createInstanceWithContext(
    OUString const & name, Reference<XComponentContext> const & xContext )
    throw (Exception)
{
    return createInstanceWithArgumentsAndContext(
        name, Sequence<Any>(), xContext );
}

//______________________________________________________________________________
Reference<XInterface> CanvasFactory::use(
    Reference<lang::XSingleComponentFactory> const & xFactory,
    Sequence<Any> const & args, Reference<XComponentContext> const & xContext )
{
    try {
        return xFactory->createInstanceWithArgumentsAndContext(args, xContext);
    }
    catch (RuntimeException &) {
        throw;
    }
    catch (Exception &) {
        return Reference<XInterface>();
    }
}

//______________________________________________________________________________
Reference<XInterface> CanvasFactory::lookupAndUse(
    OUString const & serviceName, Sequence<Any> const & args,
    Reference<XComponentContext> const & xContext )
{
    {
        // try to reuse:
        ::osl::ClearableMutexGuard guard(m_mutex);
        if (m_serviceName.equals(serviceName)) {
            Reference<lang::XSingleComponentFactory> xFac(m_xFactory);
            guard.clear();
            Reference<XInterface> xCanvas( use( xFac, args, xContext ) );
            if (xCanvas.is())
                return xCanvas;
        }
    }

    Reference<container::XContentEnumerationAccess> xEnumAccess(
        // use service manager of factory:
        m_xContext->getServiceManager(), UNO_QUERY_THROW );
    Reference<container::XEnumeration> xEnum(
        xEnumAccess->createContentEnumeration( serviceName ) );
    if (xEnum.is()) {
        while (xEnum->hasMoreElements()) {
            Reference<lang::XSingleComponentFactory> xFactory(
                xEnum->nextElement(), UNO_QUERY );
            OSL_ASSERT( xFactory.is() );
            if (xFactory.is()) {
                Reference<XInterface> xCanvas(
                    use( xFactory, args, xContext ) );
                if (xCanvas.is()) {
                    ::osl::MutexGuard guard(m_mutex);
                    // init for reuse:
                    m_xFactory.set(xFactory);
                    m_serviceName = serviceName;
                    return xCanvas;
                }
            }
        }
    }

    return Reference<XInterface>();
}

//______________________________________________________________________________
Reference<XInterface> CanvasFactory::createInstanceWithArgumentsAndContext(
    OUString const & preferredOne, Sequence<Any> const & args,
    Reference<XComponentContext> const & xContext ) throw (Exception)
{
    // preferred one overrides previously used one:
    if (preferredOne.getLength() > 0) {
        Reference<XInterface> xCanvas(
            lookupAndUse( preferredOne, args, xContext ) );
        if (xCanvas.is())
            return xCanvas;
    }

    {
        // try to reuse previously installed factory:
        ::osl::ClearableMutexGuard guard(m_mutex);
        if (m_xFactory.is()) {
            Reference<lang::XSingleComponentFactory> xFac(m_xFactory);
            guard.clear();
            Reference<XInterface> xCanvas( use( xFac, args, xContext ) );
            if (xCanvas.is())
                return xCanvas;
        }
    }

    // try configured ones:
    OUString const * pservices = m_services.getConstArray();
    sal_Int32 pos = 0, len = m_services.getLength();
    for ( ; pos < len; ++pos ) {
        Reference<XInterface> xCanvas(
            lookupAndUse( pservices[pos], args, xContext ) );
        if (xCanvas.is())
            return xCanvas;
    }

    OSL_ENSURE( 0, "### no canvas available!?" );
    return Reference<XInterface>();
}

// XMultiServiceFactory
//______________________________________________________________________________
Reference<XInterface> CanvasFactory::createInstance( OUString const & name )
    throw (Exception)
{
    return createInstanceWithArgumentsAndContext(
        name, Sequence<Any>(), m_xContext );
}

//______________________________________________________________________________
Reference<XInterface> CanvasFactory::createInstanceWithArguments(
    OUString const & name, Sequence<Any> const & args ) throw (Exception)
{
    return createInstanceWithArgumentsAndContext(
        name, args, m_xContext );
}

const ::cppu::ImplementationEntry s_entries [] = {
    {
        create,
        getImplName,
        getSuppServices,
        ::cppu::createSingleComponentFactory,
        0, 0
    },
    { 0, 0, 0, 0, 0, 0 }
};

} // anon namespace

extern "C" {

void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

sal_Bool SAL_CALL component_writeInfo(
    lang::XMultiServiceFactory * pServiceManager,
    registry::XRegistryKey * pRegistryKey )
{
    return ::cppu::component_writeInfoHelper(
        pServiceManager, pRegistryKey, s_entries );
}

void * SAL_CALL component_getFactory(
    sal_Char const * pImplName,
    lang::XMultiServiceFactory * pServiceManager,
    registry::XRegistryKey * pRegistryKey )
{
    return ::cppu::component_getFactoryHelper(
        pImplName, pServiceManager, pRegistryKey, s_entries );
}

}

<|endoftext|>


<commit_before>#include <unordered_map>
#include <string>
#include <numeric>
#include <algorithm>
#include <Rcpp.h>
using namespace Rcpp;
using namespace std;

// [[Rcpp::export]]
SEXP cpp_stack(SEXP arlist) {
    auto array_list = as<List>(arlist);
    auto dimnames = vector<vector<string>>(); // dim: names along
    auto axmap = vector<unordered_map<string, int>>(); // dim: element name->index
    auto a2r = vector<vector<vector<int>>>(array_list.size()); // array > dim > element

    // create lookup tables for all present dimension names
    for (int a=0; a<Rf_xlength(array_list); a++) { // array in arlist
        auto va = as<NumericVector>(array_list[a]);
        auto dn = as<List>(va.attr("dimnames"));
        auto da = as<vector<int>>(va.attr("dim"));

        a2r[a] = vector<vector<int>>(da.size());
        if (dimnames.size() < da.size()) {
            dimnames.resize(da.size());
            axmap.resize(da.size());
        }

        for (int d=0; d<da.size(); d++) { // dimension in array
            auto dni = as<vector<string>>(dn[d]);

            for (int e=0; e<da[d]; e++) { // element in dimension
                if (axmap[d].count(dni[e]) == 0) {
                    cout << "array " << a << " dim " << d << ": " << dni[e] << " -> " << axmap[d].size() << "\n";
                    axmap[d].emplace(dni[e], axmap[d].size());
                    dimnames[d].push_back(dni[e]);
                }
                a2r[a][d].push_back(axmap[d][dni[e]]);
            }
        }
    }

    for (auto ai=0; ai<a2r.size(); ai++)
        for (auto di=0; di<a2r[ai].size(); di++) {
            cout << "*** array " << ai << " dim " << di << ": ";
            copy(a2r[ai][di].begin(), a2r[ai][di].end(), ostream_iterator<int>(cout, " "));
            cout << "\n";
        }

    // create result array with attributes
    auto rdim = IntegerVector(dimnames.size());
    auto rdnames = List(dimnames.size());
    for (int i=0; i<dimnames.size(); i++) {
        rdim[i] = dimnames[i].size();
        rdnames[i] = CharacterVector(dimnames[i].begin(), dimnames[i].end());
    }
    auto n = accumulate(rdim.begin(), rdim.end(), 1, multiplies<int>());
    auto result = NumericVector(n);
    result.attr("dim") = rdim;
    result.attr("dimnames") = rdnames;

    // fill the result array
    auto maxdim = rdim.size() - 1;
    for (int ai=0; ai<Rf_xlength(array_list); ai++) {
        auto a = as<NumericVector>(array_list[ai]);
        auto it = vector<vector<int>::iterator>(a2r[ai].size()); // one for each result dim
        for (int rd=0; rd<it.size(); rd++)
            it[rd] = a2r[ai][rd].begin();

        int aidx = 0; // consecutive elements in original array
        do {
            int ridx_flat = *it[0];
            it[0]++;
            for (int d=0; d<maxdim; d++) {
                ridx_flat += rdim[d] * *it[d+1];

                if (it[d] == a2r[ai][d].end()) {
                    it[d] = a2r[ai][d].begin();
                    it[d+1]++;
                }
            }
            cout << "result[" << ridx_flat << "] = a[" << aidx << "++]\n";
            result[ridx_flat] = a[aidx++];
        } while(it[maxdim] != a2r[ai][maxdim].end());
    }

    return result;
}
<commit_msg>calc offset only when dim jumping<commit_after>#include <unordered_map>
#include <string>
#include <numeric>
#include <algorithm>
#include <Rcpp.h>
using namespace Rcpp;
using namespace std;

// [[Rcpp::export]]
SEXP cpp_stack(SEXP arlist) {
    auto array_list = as<List>(arlist);
    auto dimnames = vector<vector<string>>(); // dim: names along
    auto axmap = vector<unordered_map<string, int>>(); // dim: element name->index
    auto a2r = vector<vector<vector<int>>>(array_list.size()); // array > dim > element

    // create lookup tables for all present dimension names
    for (int a=0; a<Rf_xlength(array_list); a++) { // array in arlist
        auto va = as<NumericVector>(array_list[a]);
        auto dn = as<List>(va.attr("dimnames"));
        auto da = as<vector<int>>(va.attr("dim"));

        a2r[a] = vector<vector<int>>(da.size());
        if (dimnames.size() < da.size()) {
            dimnames.resize(da.size());
            axmap.resize(da.size());
        }

        for (int d=0; d<da.size(); d++) { // dimension in array
            auto dni = as<vector<string>>(dn[d]);

            for (int e=0; e<da[d]; e++) { // element in dimension
                if (axmap[d].count(dni[e]) == 0) {
                    cout << "array " << a << " dim " << d << ": " << dni[e] << " -> " << axmap[d].size() << "\n";
                    axmap[d].emplace(dni[e], axmap[d].size());
                    dimnames[d].push_back(dni[e]);
                }
                a2r[a][d].push_back(axmap[d][dni[e]]);
            }
        }
    }

    for (auto ai=0; ai<a2r.size(); ai++)
        for (auto di=0; di<a2r[ai].size(); di++) {
            cout << "*** array " << ai << " dim " << di << ": ";
            copy(a2r[ai][di].begin(), a2r[ai][di].end(), ostream_iterator<int>(cout, " "));
            cout << "\n";
        }

    // create result array with attributes
    auto rdim = IntegerVector(dimnames.size());
    auto rdnames = List(dimnames.size());
    for (int i=0; i<dimnames.size(); i++) {
        rdim[i] = dimnames[i].size();
        rdnames[i] = CharacterVector(dimnames[i].begin(), dimnames[i].end());
    }
    auto n = accumulate(rdim.begin(), rdim.end(), 1, multiplies<int>());
    auto result = NumericVector(n);
    result.attr("dim") = rdim;
    result.attr("dimnames") = rdnames;

    // fill the result array
    int maxdim = rdim.size() - 1;
    for (int ai=0; ai<Rf_xlength(array_list); ai++) {
        auto a = as<NumericVector>(array_list[ai]);
        int aidx = 0; // consecutive elements in original array

        auto it = vector<vector<int>::iterator>(a2r[ai].size()); // one for each result dim
        for (int d=0; d<it.size(); d++)
            it[d] = a2r[ai][d].begin();

        int dim_offset = 0;
        for (int d=0; d<maxdim; d++)
            dim_offset += rdim[d] * *it[d+1];

        do {
            int cur_offset = *it[0];
            int dim_offset_new = 0;
            it[0]++;
            for (int d=0; d<maxdim; d++) {
                if (it[d] != a2r[ai][d].end()) // no dimension jump
                    break;

                dim_offset_new += rdim[d]; // add only dimensions we jump
                it[d] = a2r[ai][d].begin();
                it[d+1]++;
            }

            cout << "result[" << cur_offset + dim_offset << "] = a[" << ai << "][" << aidx << "]\n";
            result[cur_offset + dim_offset] = a[aidx++];
            dim_offset += dim_offset_new;
        } while(it[maxdim] != a2r[ai][maxdim].end());
    }

    return result;
}
<|endoftext|>


<commit_before>#pragma once

#include "../src/Geometry/Geometry.hpp"
#include "../src/Geometry/convex.cpp"
#include "../src/Geometry/distance.cpp"
#include "../src/Geometry/intersect.cpp"
#include "../src/Geometry/intersect_circle.cpp"

#include "../src/Graph/Graph.hpp"
#include "../src/Graph/bfs01.cpp"
#include "../src/Graph/bipartite_matching.cpp"
#include "../src/Graph/dijkstra.cpp"
#include "../src/Graph/lca.cpp"
#include "../src/Graph/max_flow.cpp"
#include "../src/Graph/min_cost_flow.cpp"
#include "../src/Graph/recession.cpp"
#include "../src/Graph/spfa.cpp"

#include "../src/Math/eratosthenes.cpp"
#include "../src/Math/fft.cpp"
#include "../src/Math/matrix.cpp"
#include "../src/Math/mod.cpp"
#include "../src/Math/vector.cpp"

#include "../src/Others/cout.cpp"

#include "../src/String/kmp.cpp"
#include "../src/String/rolling_hash.cpp"

#include "../src/Structure/fenwick_tree.cpp"
#include "../src/Structure/rars.cpp"
#include "../src/Structure/segment_tree.cpp"
#include "../src/Structure/skew_heap.cpp"
#include "../src/Structure/slide_min.cpp"
#include "../src/Structure/starry_sky_tree.cpp"
#include "../src/Structure/unionfind.cpp"

using namespace std;

class Timer {
  double start;
public:
  Timer() : start(clock()) {}
  double stop() { return (clock() - start) / CLOCKS_PER_SEC; }
};

void print(const char *name, double t, double x) {
  t = (t + 2 * x) * 1e9;
  printf("%s : %.3f ns\n", name, t);
  // printf("%s : %.3f ns (%.3f ns - %.3f ns)\n", name, t, t - 2 * x, t + 2 * x);
}

void check(double (*f)(), const char *name) {
  const int N = 5;
  vector<double> res(N);
  for (auto &i: res) i = f();
  double ave = accumulate(begin(res), end(res), 0.0) / N;
  transform(begin(res), end(res), begin(res), [&](double x){ return pow(x - ave, 2); });
  double sd = sqrt(accumulate(begin(res), end(res), 0.0) / N);
  print(name, ave, sd);
}

mt19937 mt(0);
uniform_real_distribution<double> rnd(-100.0, 100.0);

const int array_len = 200000;
const int query_num = 1000000;

// STL

vector<int> random_array() {
  vector<int> res(array_len);
  for (auto &i: res) i = mt();
  return res;
}

// Structure

class Query {
public:
  int type, pos, left, right, value;
  Query(int len) :
    type(mt() % 2),
    pos(mt() % len), left(mt() % len), right(mt() % len),
    value(mt() % 2000 - 1000)
  {
    if (left > right) swap(left, right);
    ++right;
  }
};

vector<Query> random_query() {
  vector<Query> res(query_num, array_len);
  for (auto &i: res) i = Query(array_len);
  return res;
}

// Graph

const int vertex_num = 50000;
const int edge_num = 200000;

CGraph<int> random_cgraph(int min_cost, int max_cost) {
  CGraph<int> g(vertex_num);
  for (int i = 0; i < edge_num; ++i) {
    int from = mt() % vertex_num;
    int to = mt() % vertex_num;
    int cost = mt() % (max_cost - min_cost) + min_cost;
    add_edge(g, from, to, cost);
  }
  return g;
}

FGraph<int> random_fgraph(int V, int E, int max_flow) {
  FGraph<int> g(V);
  for (int i = 0; i < E; ++i) {
    int from = mt() % V;
    int to = mt() % V;
    int flow = mt() % max_flow;
    add_edge(g, from, to, flow);
  }
  return g;
}

FCGraph<int, int> random_fcgraph(int V, int E, int max_flow, int max_cost) {
  FCGraph<int, int> g(V);
  for (int i = 0; i < E; ++i) {
    int from = mt() % V;
    int to = mt() % V;
    int flow = mt() % max_flow;
    int cost = mt() % max_cost;
    add_edge(g, from, to, flow, cost);
  }
  return g;
}

Graph random_tree(int V) {
  vector<pair<int,int>> edges;
  for (int i = 1; i < V; ++i) {
    int p = mt() % i;
    if (mt() % 2) edges.emplace_back(i, p);
    else edges.emplace_back(p, i);
  }
  shuffle(begin(edges), end(edges), mt);
  Graph g(V);
  for (auto e: edges) add_edge(g, e.first, e.second);
  return g;
}

// Geometry

template<typename T, T (*f)()>
vector<T> vectorize() {
  vector<T> res;
  for (int i = 0; i < query_num; ++i) res.push_back(f());
  return res;
}

template<typename T>
int zero(T x) { return max(0, min(int(abs(x)), 0)); }

Point random_point() { return Point(rnd(mt), rnd(mt)); }
Segment random_segment() { return Segment(random_point(), random_point()); }
Line random_line() { return Line(random_segment()); }
Circle random_circle() { return Circle(random_point(), rnd(mt)); }
vector<Point> random_points() { return unique(vectorize<Point, random_point>()); }
vector<Segment> random_segments() { return vectorize<Segment, random_segment>(); }
vector<Line> random_lines() { return vectorize<Line, random_line>(); }
vector<Circle> random_circles() { return vectorize<Circle, random_circle>(); }

Polygon random_polygon() {
  Polygon res;
  const ld pi = acos(-1.0);
  for (int i = 0; i < query_num; ++i)
    res.push_back(polar(100.0L, 2 * pi / query_num));
  return res;
}
<commit_msg>impl hash functions<commit_after>#pragma once

#include "../src/Geometry/Geometry.hpp"
#include "../src/Geometry/convex.cpp"
#include "../src/Geometry/distance.cpp"
#include "../src/Geometry/intersect.cpp"
#include "../src/Geometry/intersect_circle.cpp"

#include "../src/Graph/Graph.hpp"
#include "../src/Graph/bfs01.cpp"
#include "../src/Graph/bipartite_matching.cpp"
#include "../src/Graph/dijkstra.cpp"
#include "../src/Graph/lca.cpp"
#include "../src/Graph/max_flow.cpp"
#include "../src/Graph/min_cost_flow.cpp"
#include "../src/Graph/recession.cpp"
#include "../src/Graph/spfa.cpp"

#include "../src/Math/eratosthenes.cpp"
#include "../src/Math/fft.cpp"
#include "../src/Math/matrix.cpp"
#include "../src/Math/mod.cpp"
#include "../src/Math/vector.cpp"

#include "../src/Others/cout.cpp"

#include "../src/String/kmp.cpp"
#include "../src/String/rolling_hash.cpp"

#include "../src/Structure/fenwick_tree.cpp"
#include "../src/Structure/rars.cpp"
#include "../src/Structure/segment_tree.cpp"
#include "../src/Structure/skew_heap.cpp"
#include "../src/Structure/slide_min.cpp"
#include "../src/Structure/starry_sky_tree.cpp"
#include "../src/Structure/unionfind.cpp"

using namespace std;

class Timer {
  double start;
public:
  Timer() : start(clock()) {}
  double stop() { return (clock() - start) / CLOCKS_PER_SEC; }
};

void print(const char *name, double t, double x) {
  t = (t + 2 * x) * 1e9;
  printf("%s : %.3f ns\n", name, t);
  // printf("%s : %.3f ns (%.3f ns - %.3f ns)\n", name, t, t - 2 * x, t + 2 * x);
}

void check(double (*f)(), const char *name) {
  const int N = 5;
  vector<double> res(N);
  for (auto &i: res) i = f();
  double ave = accumulate(begin(res), end(res), 0.0) / N;
  transform(begin(res), end(res), begin(res), [&](double x){ return pow(x - ave, 2); });
  double sd = sqrt(accumulate(begin(res), end(res), 0.0) / N);
  print(name, ave, sd);
}

mt19937 mt(0);
uniform_real_distribution<double> rnd(-100.0, 100.0);

const int array_len = 200000;
const int query_num = 1000000;

// Hash

using ull = unsigned long long;

ull my_hash(int n, mt19937 &mt) {
  return ull(n) * ull(mt());
}

ull my_hash(long long n, mt19937 &mt) {
  return ull(n) * ull(mt());
}

ull my_hash(long double n, mt19937 &mt) {
  return ull(n - 0.123456789) * ull(mt());
}

template<typename T> ull my_hash(const complex<T> &n, mt19937 &mt) {
  return my_hash(real(n), mt) + my_hash(imag(n), mt);
}

template<typename U, typename T> ull my_hash(const pair<U, T> &n, mt19937 &mt) {
  return my_hash(n.first, mt) + my_hash(n.second, mt);
}

template<typename T> ull my_hash(const vector<T> &n, mt19937 &mt) {
  ull sum = 0;
  for (const T &i: n) sum += my_hash(i, mt);
  return sum;
}

template<typename T> ull my_hash(T n) { mt19937 mt(0); return my_hash(n, mt); }

// STL

vector<int> random_array() {
  vector<int> res(array_len);
  for (auto &i: res) i = mt();
  return res;
}

// Structure

class Query {
public:
  int type, pos, left, right, value;
  Query(int len) :
    type(mt() % 2),
    pos(mt() % len), left(mt() % len), right(mt() % len),
    value(mt() % 2000 - 1000)
  {
    if (left > right) swap(left, right);
    ++right;
  }
};

vector<Query> random_query() {
  vector<Query> res(query_num, array_len);
  for (auto &i: res) i = Query(array_len);
  return res;
}

// Graph

const int vertex_num = 50000;
const int edge_num = 200000;

CGraph<int> random_cgraph(int min_cost, int max_cost) {
  CGraph<int> g(vertex_num);
  for (int i = 0; i < edge_num; ++i) {
    int from = mt() % vertex_num;
    int to = mt() % vertex_num;
    int cost = mt() % (max_cost - min_cost) + min_cost;
    add_edge(g, from, to, cost);
  }
  return g;
}

FGraph<int> random_fgraph(int V, int E, int max_flow) {
  FGraph<int> g(V);
  for (int i = 0; i < E; ++i) {
    int from = mt() % V;
    int to = mt() % V;
    int flow = mt() % max_flow;
    add_edge(g, from, to, flow);
  }
  return g;
}

FCGraph<int, int> random_fcgraph(int V, int E, int max_flow, int max_cost) {
  FCGraph<int, int> g(V);
  for (int i = 0; i < E; ++i) {
    int from = mt() % V;
    int to = mt() % V;
    int flow = mt() % max_flow;
    int cost = mt() % max_cost;
    add_edge(g, from, to, flow, cost);
  }
  return g;
}

Graph random_tree(int V) {
  vector<pair<int,int>> edges;
  for (int i = 1; i < V; ++i) {
    int p = mt() % i;
    if (mt() % 2) edges.emplace_back(i, p);
    else edges.emplace_back(p, i);
  }
  shuffle(begin(edges), end(edges), mt);
  Graph g(V);
  for (auto e: edges) add_edge(g, e.first, e.second);
  return g;
}

// Geometry

template<typename T, T (*f)()>
vector<T> vectorize() {
  vector<T> res;
  for (int i = 0; i < query_num; ++i) res.push_back(f());
  return res;
}

template<typename T>
int zero(T x) { return max(0, min(int(abs(x)), 0)); }

Point random_point() { return Point(rnd(mt), rnd(mt)); }
Segment random_segment() { return Segment(random_point(), random_point()); }
Line random_line() { return Line(random_segment()); }
Circle random_circle() { return Circle(random_point(), rnd(mt)); }
vector<Point> random_points() { return unique(vectorize<Point, random_point>()); }
vector<Segment> random_segments() { return vectorize<Segment, random_segment>(); }
vector<Line> random_lines() { return vectorize<Line, random_line>(); }
vector<Circle> random_circles() { return vectorize<Circle, random_circle>(); }

Polygon random_polygon() {
  Polygon res;
  const ld pi = acos(-1.0);
  for (int i = 0; i < query_num; ++i)
    res.push_back(polar(100.0L, 2 * pi / query_num));
  return res;
}
<|endoftext|>


<commit_before>#include "audio_nodes.h"
#include "app_globals.h"

#include <cinder/audio/Context.h>
#include <cinder/audio/MonitorNode.h>
#include <cinder/app/App.h>

#include "resampler_node.h"

namespace cieq
{

AudioNodes::AudioNodes(AppGlobals& globals)
	: mGlobals(globals)
	, mIsEnabled(false)
{}

void AudioNodes::setup(bool auto_enable /*= true*/)
{
	mInputDeviceNode = mGlobals.getAudioContext().createInputDeviceNode();

	auto monitorFormat = ci::audio::MonitorNode::Format().windowSize(1024);
	mMonitorNode = mGlobals.getAudioContext().makeNode(new ci::audio::MonitorNode(monitorFormat));

	auto monitorSpectralFormat = ci::audio::MonitorSpectralNode::Format().fftSize(2048).windowSize(1024);
	mMonitorSpectralNode = mGlobals.getAudioContext().makeNode(new ci::audio::MonitorSpectralNode(monitorSpectralFormat));

	auto resamplerFormat = cieq::audio::ResamplerNode::Format().windowSize(512).targetSampleRate(8000.0f);
	mResamplerNode = mGlobals.getAudioContext().makeNode(new audio::ResamplerNode(resamplerFormat));

	mInputDeviceNode >> mMonitorNode;
	mInputDeviceNode >> mResamplerNode;
	mInputDeviceNode >> mMonitorSpectralNode;

	ci::app::getWindow()->setTitle(ci::app::getWindow()->getTitle() + " (" + mInputDeviceNode->getDevice()->getName() + ")");

	if (auto_enable)
	{
		enableInput();
	}
}

cinder::audio::InputDeviceNode* const AudioNodes::getInputDeviceNode()
{
	return mInputDeviceNode.get();
}

cinder::audio::MonitorNode* const AudioNodes::getMonitorNode()
{
	return mMonitorNode.get();
}

cinder::audio::MonitorSpectralNode* const AudioNodes::getMonitorSpectralNode()
{
	return mMonitorSpectralNode.get();
}

void AudioNodes::enableInput()
{
	if (mIsEnabled) return;

	mGlobals.getAudioContext().enable();
	mInputDeviceNode->enable();

	mIsEnabled = true;
}

void AudioNodes::disableInput()
{
	if (!mIsEnabled) return;

	mGlobals.getAudioContext().disable();
	mInputDeviceNode->disable();

	mIsEnabled = false;
}

void AudioNodes::toggleInput()
{
	if (mIsEnabled)
	{
		disableInput();
	}
	else
	{
		enableInput();
	}
}

cieq::audio::ResamplerNode* const AudioNodes::getResamplerNode()
{
	return mResamplerNode.get();
}

} //!cieq<commit_msg>unplugging resampler node for now<commit_after>#include "audio_nodes.h"
#include "app_globals.h"

#include <cinder/audio/Context.h>
#include <cinder/audio/MonitorNode.h>
#include <cinder/app/App.h>

#include "resampler_node.h"

namespace cieq
{

AudioNodes::AudioNodes(AppGlobals& globals)
	: mGlobals(globals)
	, mIsEnabled(false)
{}

void AudioNodes::setup(bool auto_enable /*= true*/)
{
	mInputDeviceNode = mGlobals.getAudioContext().createInputDeviceNode();

	auto monitorFormat = ci::audio::MonitorNode::Format().windowSize(1024);
	mMonitorNode = mGlobals.getAudioContext().makeNode(new ci::audio::MonitorNode(monitorFormat));

	auto monitorSpectralFormat = ci::audio::MonitorSpectralNode::Format().fftSize(2048).windowSize(1024);
	mMonitorSpectralNode = mGlobals.getAudioContext().makeNode(new ci::audio::MonitorSpectralNode(monitorSpectralFormat));

	/*auto resamplerFormat = cieq::audio::ResamplerNode::Format().windowSize(512).targetSampleRate(8000.0f);
	mResamplerNode = mGlobals.getAudioContext().makeNode(new audio::ResamplerNode(resamplerFormat));*/

	mInputDeviceNode >> mMonitorNode;
	//mInputDeviceNode >> mResamplerNode;
	mInputDeviceNode >> mMonitorSpectralNode;

	ci::app::getWindow()->setTitle(ci::app::getWindow()->getTitle() + " (" + mInputDeviceNode->getDevice()->getName() + ")");

	if (auto_enable)
	{
		enableInput();
	}
}

cinder::audio::InputDeviceNode* const AudioNodes::getInputDeviceNode()
{
	return mInputDeviceNode.get();
}

cinder::audio::MonitorNode* const AudioNodes::getMonitorNode()
{
	return mMonitorNode.get();
}

cinder::audio::MonitorSpectralNode* const AudioNodes::getMonitorSpectralNode()
{
	return mMonitorSpectralNode.get();
}

void AudioNodes::enableInput()
{
	if (mIsEnabled) return;

	mGlobals.getAudioContext().enable();
	mInputDeviceNode->enable();

	mIsEnabled = true;
}

void AudioNodes::disableInput()
{
	if (!mIsEnabled) return;

	mGlobals.getAudioContext().disable();
	mInputDeviceNode->disable();

	mIsEnabled = false;
}

void AudioNodes::toggleInput()
{
	if (mIsEnabled)
	{
		disableInput();
	}
	else
	{
		enableInput();
	}
}

cieq::audio::ResamplerNode* const AudioNodes::getResamplerNode()
{
	return mResamplerNode.get();
}

} //!cieq<|endoftext|>


<commit_before>#include <catch.hpp>
#include <cmap.hpp>

using cmap::make_map;
using cmap::map;

SCENARIO("Helo") {
  constexpr auto lookup = make_map(map(1,2), map(2,3), map(5,7));
  CHECK( lookup[1] == 2 );
  CHECK( lookup[2] == 3 );
  CHECK( lookup[5] == 7 );
}
<commit_msg>Added more tests<commit_after>#include <catch.hpp>
#include <cmap.hpp>

using cmap::make_map;
using cmap::map;

SCENARIO("Compile time mapping") {
  GIVEN("a map of int -> int") {
    constexpr auto lookup = make_map(
        map(1,2),
        map(2,3),
	map(5,7)
    );
    THEN("chek each mapping") {
      CHECK( lookup[1] == 2 );
      CHECK( lookup[2] == 3 );
      CHECK( lookup[5] == 7 );
    }
  }

  GIVEN("a custom type") {
    struct MyType {
      constexpr bool operator==(const MyType& rhs) const { return value == rhs.value; }
      const int value;
    };
    GIVEN("a map of int -> custom type") {
      constexpr auto lookup = make_map(
          map(42, MyType{12}),
          map(43, MyType{13}),
          map(44, MyType{14})
      );
      THEN("check each mapping") {
	CHECK( lookup[42] == MyType{12} );
	CHECK( lookup[43] == MyType{13} );
	CHECK( lookup[44] == MyType{14} );
      }
    }

    GIVEN("a map of custom type -> int") {
      constexpr auto lookup = make_map(
          map(MyType{12}, 42),
          map(MyType{13}, 43),
          map(MyType{14}, 44)
      );
      THEN("check each mapping") {
        CHECK( lookup[MyType{12}] == 42 );
        CHECK( lookup[MyType{13}] == 43 );
        CHECK( lookup[MyType{14}] == 44 );
      }
    }
  }
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <iostream>

#include <log4cpp/Category.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/BasicLayout.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/TimeStamp.hh>

#include "Clock.hh"

// -----------------------------------------------------------------------------
int main(int argc, char* argv[])
{
    int    count  = argc > 1 ? std::atoi(argv[1]) : 100;
    size_t size   = argc > 2 ? std::atoi(argv[2]) : 128;

    std::cout << "  count: " << count << std::endl
	      << "   size: " << size  << " bytes" << std::endl
	      << std::endl;

    log4cpp::Category&	root	 = log4cpp::Category::getRoot();
    root.setPriority(log4cpp::Priority::ERROR);

    log4cpp::OstreamAppender ostreamAppender("cerr", &std::cerr);
    log4cpp::FileAppender fileAppender("stderr", fileno(stderr));
    ostreamAppender.setLayout(new log4cpp::BasicLayout());
    fileAppender.setLayout(new log4cpp::BasicLayout());

    root.removeAllAppenders();
    root.addAppender(ostreamAppender);

    log4cpp::Category& log = log4cpp::Category::getInstance("someCategory");

    Clock  clock;
    char*  buffer = new char[size + 1];

    std::memset(buffer, 'X', size + 1);
    buffer[size] = '\0';

    std::cout << "BasicLayout:" << std::endl;
    {
	clock.start();
	for (int i = 0; i < count; i++) log.error("%s", buffer);
	clock.stop();
	std::cout << "  buffer ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
        const char* buffer2 = buffer;
	clock.start();
	for (int i = 0; i < count; i++) log.error(std::string(buffer2));
	clock.stop();
	std::cout << "  buffer ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	std::string str(size, 'X');

	clock.start();
	for (int i = 0; i < count; i++)
            log << log4cpp::Priority::ERROR << str;
	clock.stop();
	std::cout << "  stream ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	std::string str(size, 'X');

	clock.start();
	for (int i = 0; i < count; i++)
            log << log4cpp::Priority::ERROR << buffer;
	clock.stop();
	std::cout << "  stream2 ostream: " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	std::string str(size, 'X');

	clock.start();
	for (int i = 0; i < count; i++) log.error(str);
	clock.stop();
	std::cout << "  string ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	std::string str(size, 'X');
        root.removeAllAppenders();
        root.addAppender(fileAppender);

	clock.start();
	for (int i = 0; i < count; i++) log.error(str);
	clock.stop();
	std::cout << "  string file:     " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    std::cout << "PatternLayout:" << std::endl;
    {
        log4cpp::PatternLayout* patternLayout = new log4cpp::PatternLayout();
        patternLayout->setConversionPattern("%R %p %c %x: %m\n");
        ostreamAppender.setLayout(patternLayout);
    }
    {
        log4cpp::PatternLayout* patternLayout = new log4cpp::PatternLayout();
        patternLayout->setConversionPattern("%R %p %c %x: %m\n");
        fileAppender.setLayout(patternLayout);
    }

    root.removeAllAppenders();
    root.addAppender(ostreamAppender);

    {
	clock.start();
	for (int i = 0; i < count; i++) log.error("%s", buffer);
	clock.stop();
	std::cout << "  buffer ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	std::string str(size, 'X');

	clock.start();
	for (int i = 0; i < count; i++) log.error(str);
	clock.stop();
	std::cout << "  string ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	std::string str(size, 'X');
        root.removeAllAppenders();
        root.addAppender(fileAppender);

	clock.start();
	for (int i = 0; i < count; i++) log.error(str);
	clock.stop();
	std::cout << "  string file:     " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	clock.start();
	for (int i = 0; i < count; i++) fprintf(stderr, "%d ERROR someCategory : %s\n", log4cpp::TimeStamp().getSeconds(), buffer);
	clock.stop();
	std::cout << std::endl << "  fprintf:        " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    log4cpp::Category::shutdown();

    return 0;
}
<commit_msg>Added tests.<commit_after>#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <iostream>

#include <log4cpp/Category.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/BasicLayout.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/TimeStamp.hh>

#include "Clock.hh"

// -----------------------------------------------------------------------------
int main(int argc, char* argv[])
{
    int    count  = argc > 1 ? std::atoi(argv[1]) : 100;
    size_t size   = argc > 2 ? std::atoi(argv[2]) : 128;

    std::cout << "  count: " << count << std::endl
	      << "   size: " << size  << " bytes" << std::endl
	      << std::endl;

    log4cpp::Category&	root	 = log4cpp::Category::getRoot();
    root.setPriority(log4cpp::Priority::ERROR);

    log4cpp::OstreamAppender ostreamAppender("cerr", &std::cerr);
    log4cpp::FileAppender fileAppender("stderr", fileno(stderr));
    ostreamAppender.setLayout(new log4cpp::BasicLayout());
    fileAppender.setLayout(new log4cpp::BasicLayout());

    root.removeAllAppenders();
    root.addAppender(ostreamAppender);

    log4cpp::Category& log = log4cpp::Category::getInstance("someCategory");

    Clock  clock;
    char*  buffer = new char[size + 1];

    std::memset(buffer, 'X', size + 1);
    buffer[size] = '\0';

    std::cout << "BasicLayout:" << std::endl;
    {
	clock.start();
	for (int i = 0; i < count; i++) log.error("%s", buffer);
	clock.stop();
	std::cout << "  charbuf printf  ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
        const char* buffer2 = buffer;
	clock.start();
	for (int i = 0; i < count; i++) log.error(std::string(buffer2));
	clock.stop();
	std::cout << "  charbuf string  ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	std::string str(size, 'X');

	clock.start();
	for (int i = 0; i < count; i++)
            log << log4cpp::Priority::ERROR << str;
	clock.stop();
	std::cout << "  string  stream  ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	clock.start();
	for (int i = 0; i < count; i++)
            log << log4cpp::Priority::ERROR << buffer;
	clock.stop();
	std::cout << "  charbuf stream  ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	std::string str(size, 'X');

	clock.start();
        log4cpp::CategoryStream s(log << log4cpp::Priority::ERROR);
	for (int i = 0; i < count; i++)
            s << str << log4cpp::CategoryStream::ENDLINE;
	clock.stop();
	std::cout << "  string  stream2 ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	clock.start();
        log4cpp::CategoryStream s(log << log4cpp::Priority::ERROR);
	for (int i = 0; i < count; i++)
            s << buffer << log4cpp::CategoryStream::ENDLINE;
	clock.stop();
	std::cout << "  charbuf stream2 ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	std::string str(size, 'X');

	clock.start();
	for (int i = 0; i < count; i++) log.error(str);
	clock.stop();
	std::cout << "  direct  string  ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	std::string str(size, 'X');
        root.removeAllAppenders();
        root.addAppender(fileAppender);

	clock.start();
	for (int i = 0; i < count; i++) log.error(str);
	clock.stop();
	std::cout << "  direct  string  file:     " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    std::cout << "PatternLayout:" << std::endl;
    {
        log4cpp::PatternLayout* patternLayout = new log4cpp::PatternLayout();
        patternLayout->setConversionPattern("%R %p %c %x: %m\n");
        ostreamAppender.setLayout(patternLayout);
    }
    {
        log4cpp::PatternLayout* patternLayout = new log4cpp::PatternLayout();
        patternLayout->setConversionPattern("%R %p %c %x: %m\n");
        fileAppender.setLayout(patternLayout);
    }

    root.removeAllAppenders();
    root.addAppender(ostreamAppender);

    {
	clock.start();
	for (int i = 0; i < count; i++) log.error("%s", buffer);
	clock.stop();
	std::cout << "  charbuf printf ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	std::string str(size, 'X');

	clock.start();
	for (int i = 0; i < count; i++) log.error(str);
	clock.stop();
	std::cout << "  direct  string ostream:  " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	std::string str(size, 'X');
        root.removeAllAppenders();
        root.addAppender(fileAppender);

	clock.start();
	for (int i = 0; i < count; i++) log.error(str);
	clock.stop();
	std::cout << "  string  file:     " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    {
	clock.start();
	for (int i = 0; i < count; i++) fprintf(stderr, "%d ERROR someCategory : %s\n", log4cpp::TimeStamp().getSeconds(), buffer);
	clock.stop();
	std::cout << std::endl << "  fprintf:        " << ((float)clock.elapsed()) / count << " us" << std::endl;
    }

    log4cpp::Category::shutdown();

    return 0;
}
<|endoftext|>


<commit_before>#include "DxContext.hpp"
#include "DxDevice.hpp"
#include "DxRenderBuffer.hpp"
#include "DxDepthStencilBuffer.hpp"
#include "DxTexture.hpp"
#include "DxSampler.hpp"
#include "DxUniformBuffer.hpp"
#include "DxVertexShader.hpp"
#include "DxPixelShader.hpp"
#include "DxVertexBuffer.hpp"
#include "VertexLayout.hpp"
#include "DxInternalInputLayout.hpp"
#include "DxInternalInputLayoutCache.hpp"
#include "DxIndexBuffer.hpp"
#include "../File.hpp"
#include "../Exception.hpp"

DxContext::DxContext(ID3D11Device* device, ID3D11DeviceContext* deviceContext)
: device(device), deviceContext(deviceContext)
{
	// создать кэш входных разметок
	inputLayoutCache = NEW(DxInternalInputLayoutCache(this));
}

ptr<DxInternalInputLayout> DxContext::CreateInternalInputLayout(VertexLayout* vertexLayout, DxVertexShader* vertexShader)
{
	try
	{
		// получить элементы разметки
		const std::vector<VertexLayout::Element>& elements = vertexLayout->GetElements();
		if(elements.empty())
			THROW_PRIMARY_EXCEPTION("Vertex layout is empty");

		// структуры описания
		// количество не указывается, так как матрицы требуют несколько элементов
		std::vector<D3D11_INPUT_ELEMENT_DESC> descs;
		// строки для имён семантик, их количество известно
		std::vector<String> semanticNames(elements.size());

		// и заполнить их
		for(size_t i = 0; i < elements.size(); ++i)
		{
			const VertexLayout::Element& element = elements[i];

			// получить количество необходимых описаний для элемента
			int needDescsCount;
			switch(element.type)
			{
			case VertexLayout::typeFloat4x4:
				needDescsCount = 4;
				break;
			default:
				needDescsCount = 1;
				break;
			}

			// выбрать формат элемента
			DXGI_FORMAT format;
			switch(element.type)
			{
			case VertexLayout::typeFloat:
				format = DXGI_FORMAT_R32_FLOAT;
				break;
			case VertexLayout::typeFloat2:
				format = DXGI_FORMAT_R32G32_FLOAT;
				break;
			case VertexLayout::typeFloat3:
				format = DXGI_FORMAT_R32G32B32_FLOAT;
				break;
			case VertexLayout::typeFloat4:
				format = DXGI_FORMAT_R32G32B32A32_FLOAT;
				break;
			case VertexLayout::typeFloat4x4:
				format = DXGI_FORMAT_R32G32B32A32_FLOAT;
				break;
			case VertexLayout::typeUInt:
				format = DXGI_FORMAT_R32_UINT;
				break;
			case VertexLayout::typeUInt2:
				format = DXGI_FORMAT_R32G32_UINT;
				break;
			case VertexLayout::typeUInt3:
				format = DXGI_FORMAT_R32G32B32_UINT;
				break;
			case VertexLayout::typeUInt4:
				format = DXGI_FORMAT_R32G32B32A32_UINT;
				break;
			default:
				THROW_PRIMARY_EXCEPTION("Unknown element type");
			}

			// размер элемента - пока всегда один вектор (float4 или uint4),
			// так как он нужен только для матриц float4x4
			const int elementSize = 16;

			// имя семантики получается переводом кода семантики в 26-ричную систему (буквы)
			String& semanticName = semanticNames[i];
			semanticName.assign('A', 8);
			int semantic = element.semantic;
			for(int j = 0; semantic; ++j)
			{
				semanticName[j] = 'A' + semantic % 26;
				semantic /= 26;
			}

			// цикл по вот этим требуемым элементам
			for(int descIndex = 0; descIndex < needDescsCount; ++descIndex)
			{
				descs.push_back(D3D11_INPUT_ELEMENT_DESC());
				D3D11_INPUT_ELEMENT_DESC& desc = descs.back();

				// SemanticName в структуре будет заполнено позже,
				// потому что сейчас адреса в векторе ещё могут поменяться

				desc.SemanticName = semanticName.c_str();
				desc.SemanticIndex = descIndex;
				desc.Format = format;
				desc.InputSlot = 0;
				desc.AlignedByteOffset = element.offset + descIndex * elementSize;
				desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
				desc.InstanceDataStepRate = 0;
			}
		}

		// получить код шейдера
		ptr<File> vertexShaderCode = vertexShader->GetCode();

		// создать разметку
		ID3D11InputLayout* inputLayoutInterface;
		if(FAILED(device->CreateInputLayout(&*descs.begin(), (UINT)descs.size(), vertexShaderCode->GetData(), vertexShaderCode->GetSize(), &inputLayoutInterface)))
			THROW_PRIMARY_EXCEPTION("Can't create input layout");

		return NEW(DxInternalInputLayout(inputLayoutInterface));
	}
	catch(Exception* exception)
	{
		THROW_SECONDARY_EXCEPTION("Can't create DX internal input layout", exception);
	}
}

void DxContext::Update()
{
	// рендертаргеты
	{
		// сейчас единственная оптимизация - количество обновляемых рендертаргетов
		int end;
		for(end = renderTargetSlotsCount - 1; end >= 0; --end)
			if(dirtyRenderBuffers[end])
				break;
		++end;

		if(end > 0 || dirtyDepthStencilBuffer)
		{
			ID3D11RenderTargetView* views[renderTargetSlotsCount];
			for(int i = 0; i < end; ++i)
			{
				RenderBuffer* abstractRenderBuffer = boundRenderBuffers[i];
				if(abstractRenderBuffer)
				{
					DxRenderBuffer* renderBuffer = fast_cast<DxRenderBuffer*>(abstractRenderBuffer);
					views[i] = renderBuffer->GetRenderTargetViewInterface();
				}
				else
					views[i] = 0;
			}

			ID3D11DepthStencilView* depthStencilView;
			DepthStencilBuffer* abstractDepthStencilBuffer = boundDepthStencilBuffer;
			if(abstractDepthStencilBuffer)
			{
				DxDepthStencilBuffer* depthStencilBuffer = fast_cast<DxDepthStencilBuffer*>(abstractDepthStencilBuffer);
				depthStencilView = depthStencilBuffer->GetDepthStencilViewInterface();
			}
			else
				depthStencilView = 0;

			// выполнить вызов
			deviceContext->OMSetRenderTargets(end, views, depthStencilView);

			// обновить флажки
			for(int i = 0; i < end; ++i)
				dirtyRenderBuffers[i] = false;
			dirtyDepthStencilBuffer = false;
		}
	}

	// текстуры
	{
		// сейчас единственная оптимизация - начало и конец в списке обновляемых текстур
		int end;
		for(end = textureSlotsCount - 1; end >= 0; --end)
			if(dirtyTextures[end])
				break;
		++end;
		int begin;
		for(begin = 0; begin < end; ++begin)
			if(dirtyTextures[begin])
				break;

		if(begin < end)
		{
			ID3D11ShaderResourceView* views[textureSlotsCount];
			for(int i = begin; i < end; ++i)
			{
				Texture* abstractTexture = boundTextures[i];
				if(abstractTexture)
				{
					DxTexture* texture = fast_cast<DxTexture*>(abstractTexture);
					views[i] = texture->GetShaderResourceViewInterface();
				}
				else
					views[i] = 0;
			}

			// установить текстуры
			deviceContext->VSSetShaderResources(begin, end - begin, views + begin);
			deviceContext->PSSetShaderResources(begin, end - begin, views + begin);

			// обновить флажки
			for(int i = begin; i < end; ++i)
				dirtyTextures[i] = false;
		}
	}

	// семплеры
	{
		// сейчас единственная оптимизация - начало и конец в списке обновляемых семплеров
		int end;
		for(end = textureSlotsCount - 1; end >= 0; --end)
			if(dirtySamplers[end])
				break;
		++end;
		int begin;
		for(begin = 0; begin < end; ++begin)
			if(dirtySamplers[begin])
				break;

		if(begin < end)
		{
			ID3D11SamplerState* states[textureSlotsCount];
			for(int i = begin; i < end; ++i)
			{
				Sampler* abstractSampler = boundSamplers[i];
				if(abstractSampler)
				{
					DxSampler* sampler = fast_cast<DxSampler*>(abstractSampler);
					states[i] = sampler->GetSamplerStateInterface();
				}
				else
					states[i] = 0;
			}

			// установить семплеры
			deviceContext->VSSetSamplers(begin, end - begin, states + begin);
			deviceContext->PSSetSamplers(begin, end - begin, states + begin);

			// обновить флажки
			for(int i = begin; i < end; ++i)
				dirtySamplers[i] = false;
		}
	}

	// константные буферы
	{
		// сейчас единственная оптимизация - начало и конец в списке обновляемых текстур
		int end;
		for(end = uniformBufferSlotsCount - 1; end >= 0; --end)
			if(dirtyUniformBuffers[end])
				break;
		++end;
		int begin;
		for(begin = 0; begin < end; ++begin)
			if(dirtyUniformBuffers[begin])
				break;

		if(begin < end)
		{
			ID3D11Buffer* buffers[uniformBufferSlotsCount];
			for(int i = begin; i < end; ++i)
			{
				UniformBuffer* abstractUniformBuffer = boundUniformBuffers[i];
				if(abstractUniformBuffer)
				{
					DxUniformBuffer* uniformBuffer = fast_cast<DxUniformBuffer*>(abstractUniformBuffer);
					buffers[i] = uniformBuffer->GetBufferInterface();
				}
				else
					buffers[i] = 0;
			}

			// установить буферы
			deviceContext->VSSetConstantBuffers(begin, end - begin, buffers + begin);
			deviceContext->PSSetConstantBuffers(begin, end - begin, buffers + begin);

			// обновить флажки
			for(int i = begin; i < end; ++i)
				dirtyUniformBuffers[i] = false;
		}
	}

	// входная разметка
	if(dirtyVertexBuffer || dirtyVertexShader)
	{
		ptr<DxInternalInputLayout> inputLayout = inputLayoutCache->GetInputLayout(boundVertexBuffer->GetVertexLayout(), fast_cast<DxVertexShader*>(&*boundVertexShader));
		if(inputLayout != boundInputLayout)
		{
			deviceContext->IASetInputLayout(inputLayout->GetInputLayoutInterface());
			boundInputLayout = inputLayout;
		}
	}

	// вершинный шейдер
	if(dirtyVertexShader)
	{
		ID3D11VertexShader* shader;
		if(boundVertexShader)
			shader = fast_cast<DxVertexShader*>(&*boundVertexShader)->GetVertexShaderInterface();
		else
			shader = 0;
		deviceContext->VSSetShader(shader, NULL, 0);

		dirtyVertexShader = false;
	}

	// пиксельный шейдер
	if(dirtyPixelShader)
	{
		ID3D11PixelShader* shader;
		if(boundPixelShader)
			shader = fast_cast<DxPixelShader*>(&*boundPixelShader)->GetPixelShaderInterface();
		else
			shader = 0;
		deviceContext->PSSetShader(shader, NULL, 0);

		dirtyPixelShader = false;
	}
}

void DxContext::SetUniformBufferData(UniformBuffer* abstractUniformBuffer, const void* data, size_t size)
{
	// проверить, что размер не больше, чем нужно
	if(size > abstractUniformBuffer->GetSize())
		THROW_PRIMARY_EXCEPTION("Data size to set into uniform buffer is too big");

	DxUniformBuffer* uniformBuffer = fast_cast<DxUniformBuffer*>(abstractUniformBuffer);

	//спроецировать буфер
	D3D11_MAPPED_SUBRESOURCE bufferData;
	ID3D11Resource* resource = uniformBuffer->GetBufferInterface();
	if(FAILED(deviceContext->Map(resource, 0, D3D11_MAP_WRITE_DISCARD, 0, &bufferData)))
		THROW_PRIMARY_EXCEPTION("Can't map graphics buffer");

	//скопировать данные
	memcpy(bufferData.pData, data, size);

	//отключить проекцию буфера
	deviceContext->Unmap(resource, 0);
}

void DxContext::Draw()
{
	Update();

	if(boundIndexBuffer)
		deviceContext->DrawIndexed(boundIndexBuffer->GetIndicesCount(), 0, 0);
	else
		deviceContext->Draw(boundVertexBuffer->GetVerticesCount(), 0);
}

void DxContext::DrawInstanced(int instancesCount)
{
	Update();

	if(boundIndexBuffer)
		deviceContext->DrawIndexedInstanced(boundIndexBuffer->GetIndicesCount(), instancesCount, 0, 0, 0);
	else
		deviceContext->DrawInstanced(boundVertexBuffer->GetVerticesCount(), instancesCount, 0, 0);
}
<commit_msg>DxContext changed according to context refactoring<commit_after>#include "DxContext.hpp"
#include "DxDevice.hpp"
#include "DxRenderBuffer.hpp"
#include "DxDepthStencilBuffer.hpp"
#include "DxTexture.hpp"
#include "DxSampler.hpp"
#include "DxUniformBuffer.hpp"
#include "DxVertexShader.hpp"
#include "DxPixelShader.hpp"
#include "DxVertexBuffer.hpp"
#include "VertexLayout.hpp"
#include "DxInternalInputLayout.hpp"
#include "DxInternalInputLayoutCache.hpp"
#include "DxIndexBuffer.hpp"
#include "../File.hpp"
#include "../Exception.hpp"

DxContext::DxContext(ID3D11Device* device, ID3D11DeviceContext* deviceContext)
: device(device), deviceContext(deviceContext)
{
	// создать кэш входных разметок
	inputLayoutCache = NEW(DxInternalInputLayoutCache(this));
}

ptr<DxInternalInputLayout> DxContext::CreateInternalInputLayout(VertexLayout* vertexLayout, DxVertexShader* vertexShader)
{
	try
	{
		// получить элементы разметки
		const std::vector<VertexLayout::Element>& elements = vertexLayout->GetElements();
		if(elements.empty())
			THROW_PRIMARY_EXCEPTION("Vertex layout is empty");

		// структуры описания
		// количество не указывается, так как матрицы требуют несколько элементов
		std::vector<D3D11_INPUT_ELEMENT_DESC> descs;
		// строки для имён семантик, их количество известно
		std::vector<String> semanticNames(elements.size());

		// и заполнить их
		for(size_t i = 0; i < elements.size(); ++i)
		{
			const VertexLayout::Element& element = elements[i];

			// получить количество необходимых описаний для элемента
			int needDescsCount;
			switch(element.type)
			{
			case VertexLayout::typeFloat4x4:
				needDescsCount = 4;
				break;
			default:
				needDescsCount = 1;
				break;
			}

			// выбрать формат элемента
			DXGI_FORMAT format;
			switch(element.type)
			{
			case VertexLayout::typeFloat:
				format = DXGI_FORMAT_R32_FLOAT;
				break;
			case VertexLayout::typeFloat2:
				format = DXGI_FORMAT_R32G32_FLOAT;
				break;
			case VertexLayout::typeFloat3:
				format = DXGI_FORMAT_R32G32B32_FLOAT;
				break;
			case VertexLayout::typeFloat4:
				format = DXGI_FORMAT_R32G32B32A32_FLOAT;
				break;
			case VertexLayout::typeFloat4x4:
				format = DXGI_FORMAT_R32G32B32A32_FLOAT;
				break;
			case VertexLayout::typeUInt:
				format = DXGI_FORMAT_R32_UINT;
				break;
			case VertexLayout::typeUInt2:
				format = DXGI_FORMAT_R32G32_UINT;
				break;
			case VertexLayout::typeUInt3:
				format = DXGI_FORMAT_R32G32B32_UINT;
				break;
			case VertexLayout::typeUInt4:
				format = DXGI_FORMAT_R32G32B32A32_UINT;
				break;
			default:
				THROW_PRIMARY_EXCEPTION("Unknown element type");
			}

			// размер элемента - пока всегда один вектор (float4 или uint4),
			// так как он нужен только для матриц float4x4
			const int elementSize = 16;

			// имя семантики получается переводом кода семантики в 26-ричную систему (буквы)
			String& semanticName = semanticNames[i];
			semanticName.assign('A', 8);
			int semantic = element.semantic;
			for(int j = 0; semantic; ++j)
			{
				semanticName[j] = 'A' + semantic % 26;
				semantic /= 26;
			}

			// цикл по вот этим требуемым элементам
			for(int descIndex = 0; descIndex < needDescsCount; ++descIndex)
			{
				descs.push_back(D3D11_INPUT_ELEMENT_DESC());
				D3D11_INPUT_ELEMENT_DESC& desc = descs.back();

				// SemanticName в структуре будет заполнено позже,
				// потому что сейчас адреса в векторе ещё могут поменяться

				desc.SemanticName = semanticName.c_str();
				desc.SemanticIndex = descIndex;
				desc.Format = format;
				desc.InputSlot = 0;
				desc.AlignedByteOffset = element.offset + descIndex * elementSize;
				desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
				desc.InstanceDataStepRate = 0;
			}
		}

		// получить код шейдера
		ptr<File> vertexShaderCode = vertexShader->GetCode();

		// создать разметку
		ID3D11InputLayout* inputLayoutInterface;
		if(FAILED(device->CreateInputLayout(&*descs.begin(), (UINT)descs.size(), vertexShaderCode->GetData(), vertexShaderCode->GetSize(), &inputLayoutInterface)))
			THROW_PRIMARY_EXCEPTION("Can't create input layout");

		return NEW(DxInternalInputLayout(inputLayoutInterface));
	}
	catch(Exception* exception)
	{
		THROW_SECONDARY_EXCEPTION("Can't create DX internal input layout", exception);
	}
}

void DxContext::Update()
{
	// рендертаргеты
	{
		// сейчас единственная оптимизация - количество обновляемых рендертаргетов
		int end;
		for(end = ContextState::renderTargetSlotsCount - 1; end >= 0; --end)
			if(targetState.renderBuffers[end] != boundState.renderBuffers[end])
				break;
		++end;

		if(end > 0 || targetState.depthStencilBuffer != boundState.depthStencilBuffer)
		{
			ID3D11RenderTargetView* views[ContextState::renderTargetSlotsCount];
			for(int i = 0; i < end; ++i)
			{
				RenderBuffer* abstractRenderBuffer = targetState.renderBuffers[i];
				if(abstractRenderBuffer)
				{
					DxRenderBuffer* renderBuffer = fast_cast<DxRenderBuffer*>(abstractRenderBuffer);
					views[i] = renderBuffer->GetRenderTargetViewInterface();
				}
				else
					views[i] = 0;
			}

			ID3D11DepthStencilView* depthStencilView;
			DepthStencilBuffer* abstractDepthStencilBuffer = targetState.depthStencilBuffer;
			if(abstractDepthStencilBuffer)
			{
				DxDepthStencilBuffer* depthStencilBuffer = fast_cast<DxDepthStencilBuffer*>(abstractDepthStencilBuffer);
				depthStencilView = depthStencilBuffer->GetDepthStencilViewInterface();
			}
			else
				depthStencilView = 0;

			// выполнить вызов
			deviceContext->OMSetRenderTargets(end, views, depthStencilView);

			// обновить актуальное состояние
			for(int i = 0; i < end; ++i)
				boundState.renderBuffers[i] = targetState.renderBuffers[i];
			boundState.depthStencilBuffer = targetState.depthStencilBuffer;
		}
	}

	// текстуры
	{
		// сейчас единственная оптимизация - начало и конец в списке обновляемых текстур
		int end;
		for(end = ContextState::textureSlotsCount - 1; end >= 0; --end)
			if(targetState.textures[end] != boundState.textures[end])
				break;
		++end;
		int begin;
		for(begin = 0; begin < end; ++begin)
			if(targetState.textures[begin] != boundState.textures[begin])
				break;

		if(begin < end)
		{
			ID3D11ShaderResourceView* views[ContextState::textureSlotsCount];
			for(int i = begin; i < end; ++i)
			{
				Texture* abstractTexture = targetState.textures[i];
				if(abstractTexture)
				{
					DxTexture* texture = fast_cast<DxTexture*>(abstractTexture);
					views[i] = texture->GetShaderResourceViewInterface();
				}
				else
					views[i] = 0;
			}

			// установить текстуры
			deviceContext->VSSetShaderResources(begin, end - begin, views + begin);
			deviceContext->PSSetShaderResources(begin, end - begin, views + begin);

			// обновить актуальное состояние
			for(int i = begin; i < end; ++i)
				boundState.textures[i] = targetState.textures[i];
		}
	}

	// семплеры
	{
		// сейчас единственная оптимизация - начало и конец в списке обновляемых семплеров
		int end;
		for(end = ContextState::textureSlotsCount - 1; end >= 0; --end)
			if(targetState.samplers[end] != boundState.samplers[end])
				break;
		++end;
		int begin;
		for(begin = 0; begin < end; ++begin)
			if(targetState.samplers[begin] != boundState.samplers[begin])
				break;

		if(begin < end)
		{
			ID3D11SamplerState* states[ContextState::textureSlotsCount];
			for(int i = begin; i < end; ++i)
			{
				Sampler* abstractSampler = targetState.samplers[i];
				if(abstractSampler)
				{
					DxSampler* sampler = fast_cast<DxSampler*>(abstractSampler);
					states[i] = sampler->GetSamplerStateInterface();
				}
				else
					states[i] = 0;
			}

			// установить семплеры
			deviceContext->VSSetSamplers(begin, end - begin, states + begin);
			deviceContext->PSSetSamplers(begin, end - begin, states + begin);

			// обновить актуальное состояние
			for(int i = begin; i < end; ++i)
				boundState.samplers[i] = targetState.samplers[i];
		}
	}

	// константные буферы
	{
		// сейчас единственная оптимизация - начало и конец в списке обновляемых текстур
		int end;
		for(end = ContextState::uniformBufferSlotsCount - 1; end >= 0; --end)
			if(targetState.uniformBuffers[end] != boundState.uniformBuffers[end])
				break;
		++end;
		int begin;
		for(begin = 0; begin < end; ++begin)
			if(targetState.uniformBuffers[begin] != boundState.uniformBuffers[begin])
				break;

		if(begin < end)
		{
			ID3D11Buffer* buffers[ContextState::uniformBufferSlotsCount];
			for(int i = begin; i < end; ++i)
			{
				UniformBuffer* abstractUniformBuffer = targetState.uniformBuffers[i];
				if(abstractUniformBuffer)
				{
					DxUniformBuffer* uniformBuffer = fast_cast<DxUniformBuffer*>(abstractUniformBuffer);
					buffers[i] = uniformBuffer->GetBufferInterface();
				}
				else
					buffers[i] = 0;
			}

			// установить буферы
			deviceContext->VSSetConstantBuffers(begin, end - begin, buffers + begin);
			deviceContext->PSSetConstantBuffers(begin, end - begin, buffers + begin);

			// обновить актуальное состояние
			for(int i = begin; i < end; ++i)
				boundState.uniformBuffers[i] = targetState.uniformBuffers[i];
		}
	}

	// входная разметка
	if(targetState.vertexBuffer != boundState.vertexBuffer || targetState.vertexShader != boundState.vertexShader)
	{
		ptr<DxInternalInputLayout> inputLayout = inputLayoutCache->GetInputLayout(targetState.vertexBuffer->GetVertexLayout(), fast_cast<DxVertexShader*>(&*targetState.vertexShader));
		if(inputLayout != boundInputLayout)
		{
			deviceContext->IASetInputLayout(inputLayout->GetInputLayoutInterface());
			boundInputLayout = inputLayout;
		}
	}

	// вершинный шейдер
	if(targetState.vertexShader != boundState.vertexShader)
	{
		ID3D11VertexShader* shader;
		if(targetState.vertexShader)
			shader = fast_cast<DxVertexShader*>(&*targetState.vertexShader)->GetVertexShaderInterface();
		else
			shader = 0;
		deviceContext->VSSetShader(shader, NULL, 0);

		boundState.vertexShader = targetState.vertexShader;
	}

	// пиксельный шейдер
	if(targetState.pixelShader != boundState.pixelShader)
	{
		ID3D11PixelShader* shader;
		if(targetState.pixelShader)
			shader = fast_cast<DxPixelShader*>(&*targetState.pixelShader)->GetPixelShaderInterface();
		else
			shader = 0;
		deviceContext->PSSetShader(shader, NULL, 0);

		boundState.pixelShader = targetState.pixelShader;
	}
}

void DxContext::SetUniformBufferData(UniformBuffer* abstractUniformBuffer, const void* data, size_t size)
{
	// проверить, что размер не больше, чем нужно
	if(size > abstractUniformBuffer->GetSize())
		THROW_PRIMARY_EXCEPTION("Data size to set into uniform buffer is too big");

	DxUniformBuffer* uniformBuffer = fast_cast<DxUniformBuffer*>(abstractUniformBuffer);

	//спроецировать буфер
	D3D11_MAPPED_SUBRESOURCE bufferData;
	ID3D11Resource* resource = uniformBuffer->GetBufferInterface();
	if(FAILED(deviceContext->Map(resource, 0, D3D11_MAP_WRITE_DISCARD, 0, &bufferData)))
		THROW_PRIMARY_EXCEPTION("Can't map graphics buffer");

	//скопировать данные
	memcpy(bufferData.pData, data, size);

	//отключить проекцию буфера
	deviceContext->Unmap(resource, 0);
}

void DxContext::Draw()
{
	Update();

	if(boundState.indexBuffer)
		deviceContext->DrawIndexed(boundState.indexBuffer->GetIndicesCount(), 0, 0);
	else
		deviceContext->Draw(boundState.vertexBuffer->GetVerticesCount(), 0);
}

void DxContext::DrawInstanced(int instancesCount)
{
	Update();

	if(boundState.indexBuffer)
		deviceContext->DrawIndexedInstanced(boundState.indexBuffer->GetIndicesCount(), instancesCount, 0, 0, 0);
	else
		deviceContext->DrawInstanced(boundState.vertexBuffer->GetVerticesCount(), instancesCount, 0, 0);
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkImagingFactory.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
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 name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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 REGENTS 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 "vtkObjectFactory.h"
#include "vtkImagingFactory.h"
#include "vtkToolkits.h"

#ifdef VTK_USE_OGLR
#include "vtkOpenGLImageMapper.h"
#include "vtkOpenGLImager.h"
#include "vtkOpenGLImageWindow.h"
#include "vtkXOpenGLTextMapper.h"
#include "vtkOpenGLPolyDataMapper2D.h"
#endif

#ifdef VTK_USE_MESA
#include "vtkMesaImageMapper.h"
#include "vtkMesaImager.h"
#include "vtkMesaImageWindow.h"
#include "vtkXMesaTextMapper.h"
#include "vtkMesaPolyDataMapper2D.h"
#endif

#ifdef _WIN32
#include "vtkOpenGLImageMapper.h"
#include "vtkOpenGLImager.h"
#include "vtkWin32OpenGLImageWindow.h"
#include "vtkWin32OpenGLTextMapper.h"
#include "vtkOpenGLPolyDataMapper2D.h"
#include "vtkWin32TextMapper.h"
#include "vtkWin32ImageWindow.h"
#include "vtkWin32ImageMapper.h"
#include "vtkWin32PolyDataMapper2D.h"
#else
#include "vtkXTextMapper.h"
#include "vtkXImageWindow.h"
#include "vtkXImageMapper.h"
#include "vtkXPolyDataMapper2D.h"
#endif

const char *vtkImagingFactoryGetRenderLibrary()
{
  const char *temp;

  // first check the environment variable
  temp = getenv("VTK_RENDERER");

  // Backward compatibility
  if ( temp )
    {
    if (!strcmp("oglr",temp))
      {
      temp = "OpenGL";
      }
    else if (!strcmp("woglr",temp))
      {
      temp = "Win32OpenGL";
      }
    else if (strcmp("Mesa",temp) && strcmp("OpenGL",temp) &&
	     strcmp("Win32OpenGL",temp))
      {
      vtkGenericWarningMacro(<<"VTK_RENDERER set to unsupported type:" << temp);
      temp = NULL;
      }
    }

  // if the environment variable is set to openGL and the user
  //  does not have opengl but they do have mesa, then use it
#ifndef VTK_USE_OGLR
#ifdef VTK_USE_MESA
	if ( temp != NULL )
	{
		if (!strcmp("OpenGL",temp))
		{
			temp = "Mesa";
		}
	}
#endif
#endif

  // if nothing is set then work down the list of possible renderers
  if ( !temp )
    {
#ifdef VTK_USE_MESA
    temp = "Mesa";
#endif
#ifdef VTK_USE_OGLR
    temp = "OpenGL";
#endif
#ifdef _WIN32
    temp = "Win32OpenGL";
#endif
    }

  return temp;
}

vtkObject* vtkImagingFactory::CreateInstance(const char* vtkclassname )
{
  // first check the object factory
  vtkObject *ret = vtkObjectFactory::CreateInstance(vtkclassname);
  if (ret)
    {
    return ret;
    }

  const char *rl = vtkImagingFactoryGetRenderLibrary();

#ifdef VTK_USE_OGLR
#ifdef VTK_USE_NATIVE_IMAGING
    if(strcmp(vtkclassname, "vtkTextMapper") == 0)
      {
      return vtkXTextMapper::New();
      }
    if(strcmp(vtkclassname, "vtkImageWindow") == 0)
      {
      return vtkXImageWindow::New();
      }
    if(strcmp(vtkclassname, "vtkImageMapper") == 0)
      {
      return vtkXImageMapper::New();
      }
    if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0)
      {
      return vtkXPolyDataMapper2D::New();
      }
#else
  if (!strcmp("OpenGL",rl))
    {
    if(strcmp(vtkclassname, "vtkTextMapper") == 0)
      {
      return vtkXOpenGLTextMapper::New();
      }
    if(strcmp(vtkclassname, "vtkImageWindow") == 0)
      {
      return vtkOpenGLImageWindow::New();
      }
    if(strcmp(vtkclassname, "vtkImager") == 0)
      {
      return vtkOpenGLImager::New();
      }
    if(strcmp(vtkclassname, "vtkImageMapper") == 0)
      {
      return vtkOpenGLImageMapper::New();
      }
    if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0)
      {
      return vtkOpenGLPolyDataMapper2D::New();
      }
    }
#endif
#endif

#ifdef _WIN32
#ifdef VTK_USE_NATIVE_IMAGING
  if(strcmp(vtkclassname, "vtkTextMapper") == 0)
    {
    return vtkWin32TextMapper::New();
    }
  if(strcmp(vtkclassname, "vtkImageWindow") == 0)
    {
    return vtkWin32ImageWindow::New();
    }
  if(strcmp(vtkclassname, "vtkImageMapper") == 0)
    {
    return vtkWin32ImageMapper::New();
    }
  if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0)
    {
    return vtkWin32PolyDataMapper2D::New();
    }
#else
  if (!strcmp("Win32OpenGL",rl))
    {
    if(strcmp(vtkclassname, "vtkTextMapper") == 0)
      {
      return vtkWin32OpenGLTextMapper::New();
      }
    if(strcmp(vtkclassname, "vtkImageWindow") == 0)
      {
      return vtkWin32OpenGLImageWindow::New();
      }
    if(strcmp(vtkclassname, "vtkImager") == 0)
      {
      return vtkOpenGLImager::New();
      }
    if(strcmp(vtkclassname, "vtkImageMapper") == 0)
      {
      return vtkOpenGLImageMapper::New();
      }
    if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0)
      {
      return vtkOpenGLPolyDataMapper2D::New();
      }
    }
#endif
#endif

#ifdef VTK_USE_MESA
#ifdef VTK_USE_NATIVE_IMAGING
    if(strcmp(vtkclassname, "vtkTextMapper") == 0)
      {
      return vtkXTextMapper::New();
      }
    if(strcmp(vtkclassname, "vtkImageWindow") == 0)
      {
      return vtkXImageWindow::New();
      }
    if(strcmp(vtkclassname, "vtkImageMapper") == 0)
      {
      return vtkXImageMapper::New();
      }
    if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0)
      {
      return vtkXPolyDataMapper2D::New();
      }
#else
  if (!strcmp("Mesa",rl))
    {
    if(strcmp(vtkclassname, "vtkTextMapper") == 0)
      {
      return vtkXMesaTextMapper::New();
      }
    if(strcmp(vtkclassname, "vtkImageWindow") == 0)
      {
      return vtkMesaImageWindow::New();
      }
    if(strcmp(vtkclassname, "vtkImager") == 0)
      {
      return vtkMesaImager::New();
      }
    if(strcmp(vtkclassname, "vtkImageMapper") == 0)
      {
      return vtkMesaImageMapper::New();
      }
    if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0)
      {
      return vtkMesaPolyDataMapper2D::New();
      }
    }
#endif
#endif
  vtkGenericWarningMacro("Attempting to create an OpenGL or Mesa based object with a VTK that is not linked/configured with Mesa/OpenGL.");
  abort();
  return 0;
}

<commit_msg>ERR: Was failing if VTK_USE_NATIVE_IMAGING was set and vtkImager was created.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImagingFactory.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
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 name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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 REGENTS 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 "vtkObjectFactory.h"
#include "vtkImagingFactory.h"
#include "vtkToolkits.h"

#ifdef VTK_USE_OGLR
#include "vtkOpenGLImageMapper.h"
#include "vtkOpenGLImager.h"
#include "vtkOpenGLImageWindow.h"
#include "vtkXOpenGLTextMapper.h"
#include "vtkOpenGLPolyDataMapper2D.h"
#endif

#ifdef VTK_USE_MESA
#include "vtkMesaImageMapper.h"
#include "vtkMesaImager.h"
#include "vtkMesaImageWindow.h"
#include "vtkXMesaTextMapper.h"
#include "vtkMesaPolyDataMapper2D.h"
#endif

#ifdef _WIN32
#include "vtkOpenGLImageMapper.h"
#include "vtkOpenGLImager.h"
#include "vtkWin32OpenGLImageWindow.h"
#include "vtkWin32OpenGLTextMapper.h"
#include "vtkOpenGLPolyDataMapper2D.h"
#include "vtkWin32TextMapper.h"
#include "vtkWin32ImageWindow.h"
#include "vtkWin32ImageMapper.h"
#include "vtkWin32PolyDataMapper2D.h"
#else
#include "vtkXTextMapper.h"
#include "vtkXImageWindow.h"
#include "vtkXImageMapper.h"
#include "vtkXPolyDataMapper2D.h"
#endif

const char *vtkImagingFactoryGetRenderLibrary()
{
  const char *temp;

  // first check the environment variable
  temp = getenv("VTK_RENDERER");

  // Backward compatibility
  if ( temp )
    {
    if (!strcmp("oglr",temp))
      {
      temp = "OpenGL";
      }
    else if (!strcmp("woglr",temp))
      {
      temp = "Win32OpenGL";
      }
    else if (strcmp("Mesa",temp) && strcmp("OpenGL",temp) &&
	     strcmp("Win32OpenGL",temp))
      {
      vtkGenericWarningMacro(<<"VTK_RENDERER set to unsupported type:" << temp);
      temp = NULL;
      }
    }

  // if the environment variable is set to openGL and the user
  //  does not have opengl but they do have mesa, then use it
#ifndef VTK_USE_OGLR
#ifdef VTK_USE_MESA
	if ( temp != NULL )
	{
		if (!strcmp("OpenGL",temp))
		{
			temp = "Mesa";
		}
	}
#endif
#endif

  // if nothing is set then work down the list of possible renderers
  if ( !temp )
    {
#ifdef VTK_USE_MESA
    temp = "Mesa";
#endif
#ifdef VTK_USE_OGLR
    temp = "OpenGL";
#endif
#ifdef _WIN32
    temp = "Win32OpenGL";
#endif
    }

  return temp;
}

vtkObject* vtkImagingFactory::CreateInstance(const char* vtkclassname )
{
  // first check the object factory
  vtkObject *ret = vtkObjectFactory::CreateInstance(vtkclassname);
  if (ret)
    {
    return ret;
    }

  const char *rl = vtkImagingFactoryGetRenderLibrary();

#ifdef VTK_USE_OGLR
#ifdef VTK_USE_NATIVE_IMAGING
    if(strcmp(vtkclassname, "vtkTextMapper") == 0)
      {
      return vtkXTextMapper::New();
      }
    if(strcmp(vtkclassname, "vtkImageWindow") == 0)
      {
      return vtkXImageWindow::New();
      }
    if(strcmp(vtkclassname, "vtkImager") == 0)
      {
      return NULL;
      }
    if(strcmp(vtkclassname, "vtkImageMapper") == 0)
      {
      return vtkXImageMapper::New();
      }
    if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0)
      {
      return vtkXPolyDataMapper2D::New();
      }
#else
  if (!strcmp("OpenGL",rl))
    {
    if(strcmp(vtkclassname, "vtkTextMapper") == 0)
      {
      return vtkXOpenGLTextMapper::New();
      }
    if(strcmp(vtkclassname, "vtkImageWindow") == 0)
      {
      return vtkOpenGLImageWindow::New();
      }
    if(strcmp(vtkclassname, "vtkImager") == 0)
      {
      return vtkOpenGLImager::New();
      }
    if(strcmp(vtkclassname, "vtkImageMapper") == 0)
      {
      return vtkOpenGLImageMapper::New();
      }
    if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0)
      {
      return vtkOpenGLPolyDataMapper2D::New();
      }
    }
#endif
#endif

#ifdef _WIN32
#ifdef VTK_USE_NATIVE_IMAGING
  if(strcmp(vtkclassname, "vtkTextMapper") == 0)
    {
    return vtkWin32TextMapper::New();
    }
  if(strcmp(vtkclassname, "vtkImageWindow") == 0)
    {
    return vtkWin32ImageWindow::New();
    }
  if(strcmp(vtkclassname, "vtkImageMapper") == 0)
    {
    return vtkWin32ImageMapper::New();
    }
  if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0)
    {
    return vtkWin32PolyDataMapper2D::New();
    }
#else
  if (!strcmp("Win32OpenGL",rl))
    {
    if(strcmp(vtkclassname, "vtkTextMapper") == 0)
      {
      return vtkWin32OpenGLTextMapper::New();
      }
    if(strcmp(vtkclassname, "vtkImageWindow") == 0)
      {
      return vtkWin32OpenGLImageWindow::New();
      }
    if(strcmp(vtkclassname, "vtkImager") == 0)
      {
      return vtkOpenGLImager::New();
      }
    if(strcmp(vtkclassname, "vtkImageMapper") == 0)
      {
      return vtkOpenGLImageMapper::New();
      }
    if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0)
      {
      return vtkOpenGLPolyDataMapper2D::New();
      }
    }
#endif
#endif

#ifdef VTK_USE_MESA
#ifdef VTK_USE_NATIVE_IMAGING
    if(strcmp(vtkclassname, "vtkTextMapper") == 0)
      {
      return vtkXTextMapper::New();
      }
    if(strcmp(vtkclassname, "vtkImageWindow") == 0)
      {
      return vtkXImageWindow::New();
      }
    if(strcmp(vtkclassname, "vtkImageMapper") == 0)
      {
      return vtkXImageMapper::New();
      }
    if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0)
      {
      return vtkXPolyDataMapper2D::New();
      }
#else
  if (!strcmp("Mesa",rl))
    {
    if(strcmp(vtkclassname, "vtkTextMapper") == 0)
      {
      return vtkXMesaTextMapper::New();
      }
    if(strcmp(vtkclassname, "vtkImageWindow") == 0)
      {
      return vtkMesaImageWindow::New();
      }
    if(strcmp(vtkclassname, "vtkImager") == 0)
      {
      return vtkMesaImager::New();
      }
    if(strcmp(vtkclassname, "vtkImageMapper") == 0)
      {
      return vtkMesaImageMapper::New();
      }
    if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0)
      {
      return vtkMesaPolyDataMapper2D::New();
      }
    }
#endif
#endif
  vtkGenericWarningMacro("Attempting to create an OpenGL or Mesa based object with a VTK that is not linked/configured with Mesa/OpenGL.");
  abort();
  return 0;
}

<|endoftext|>