<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <toolkit/helper/accessibilityclient.hxx>
#include <toolkit/helper/accessiblefactory.hxx>
#include <osl/module.h>
#include <osl/diagnose.h>
#include <tools/solar.h>

// #define UNLOAD_ON_LAST_CLIENT_DYING
    // this is not recommended currently. If enabled, the implementation will log
    // the number of active clients, and unload the acc library when the last client
    // goes away.
    // Sounds like a good idea, unfortunately, there's no guarantee that all objects
    // implemented in this library are already dead.
    // Iow, just because an object implementing an XAccessible (implemented in this lib
    // here) died, it's not said that everybody released all references to the
    // XAccessibleContext used by this component, and implemented in the acc lib.
    // So we cannot really unload the lib.

    // Alternatively, if the lib would us own "usage counting", i.e. every component
    // implemented therein would affect a static ref count, the acc lib could care
    // for unloading itself.

namespace toolkit
{

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

    namespace
    {
#ifdef UNLOAD_ON_LAST_CLIENT_DYING
        static oslInterlockedCount                      s_nAccessibilityClients = 0;
#endif // UNLOAD_ON_LAST_CLIENT_DYING
#ifndef DISABLE_DYNLOADING
        static oslModule                                s_hAccessibleImplementationModule = NULL;
#endif
        static GetStandardAccComponentFactory           s_pAccessibleFactoryFunc = NULL;
        static ::rtl::Reference< IAccessibleFactory >   s_pFactory;
    }

    //= AccessibleDummyFactory

    class AccessibleDummyFactory : public IAccessibleFactory
    {
    public:
        AccessibleDummyFactory();

    protected:
        virtual ~AccessibleDummyFactory();

    private:
        AccessibleDummyFactory( const AccessibleDummyFactory& );            // never implemented
        AccessibleDummyFactory& operator=( const AccessibleDummyFactory& ); // never implemented

        oslInterlockedCount m_refCount;

    public:
        // IReference
        virtual oslInterlockedCount SAL_CALL acquire();
        virtual oslInterlockedCount SAL_CALL release();

        // IAccessibleFactory
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXButton* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXCheckBox* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXRadioButton* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXListBox* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXFixedHyperlink* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXFixedText* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXScrollBar* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXEdit* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXComboBox* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXToolBox* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXWindow* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
                createAccessible( Menu* /*_pMenu*/, sal_Bool /*_bIsMenuBar*/ )
        {
            return NULL;
        }
    };

    AccessibleDummyFactory::AccessibleDummyFactory()
    {
    }

    AccessibleDummyFactory::~AccessibleDummyFactory()
    {
    }

    oslInterlockedCount SAL_CALL AccessibleDummyFactory::acquire()
    {
        return osl_atomic_increment( &m_refCount );
    }

    oslInterlockedCount SAL_CALL AccessibleDummyFactory::release()
    {
        if ( 0 == osl_atomic_decrement( &m_refCount ) )
        {
            delete this;
            return 0;
        }
        return m_refCount;
    }

    //= AccessibilityClient

    AccessibilityClient::AccessibilityClient()
        :m_bInitialized( false )
    {
    }

#ifndef DISABLE_DYNLOADING
    extern "C" { static void SAL_CALL thisModule() {} }
#else
    extern "C" void *getStandardAccessibleFactory();
#endif

    void AccessibilityClient::ensureInitialized()
    {
        if ( m_bInitialized )
            return;

        ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );

#ifdef UNLOAD_ON_LAST_CLIENT_DYING
        if ( 1 == osl_atomic_increment( &s_nAccessibilityClients ) )
        {   // the first client
#endif // UNLOAD_ON_LAST_CLIENT_DYING
            // load the library implementing the factory
            if ( !s_pFactory.get() )
            {
#ifndef DISABLE_DYNLOADING
                const OUString sModuleName( SVLIBRARY( "acc" ) );
                s_hAccessibleImplementationModule = osl_loadModuleRelative( &thisModule, sModuleName.pData, 0 );
                if ( s_hAccessibleImplementationModule != NULL )
                {
                    const OUString sFactoryCreationFunc =
                        OUString("getStandardAccessibleFactory");
                    s_pAccessibleFactoryFunc = (GetStandardAccComponentFactory)
                        osl_getFunctionSymbol( s_hAccessibleImplementationModule, sFactoryCreationFunc.pData );

                }
                OSL_ENSURE( s_pAccessibleFactoryFunc, "AccessibilityClient::ensureInitialized: could not load the library, or not retrieve the needed symbol!" );
#else
                s_pAccessibleFactoryFunc = getStandardAccessibleFactory;
#endif

                // get a factory instance
                if ( s_pAccessibleFactoryFunc )
                {
                    IAccessibleFactory* pFactory = static_cast< IAccessibleFactory* >( (*s_pAccessibleFactoryFunc)() );
                    OSL_ENSURE( pFactory, "AccessibilityClient::ensureInitialized: no factory provided by the A11Y lib!" );
                    if ( pFactory )
                    {
                        s_pFactory = pFactory;
                        pFactory->release();
                    }
                }
            }

            if ( !s_pFactory.get() )
                // the attempt to load the lib, or to create the factory, failed
                // -> fall back to a dummy factory
                s_pFactory = new AccessibleDummyFactory;
#ifdef UNLOAD_ON_LAST_CLIENT_DYING
        }
#endif

        m_bInitialized = true;
    }

    AccessibilityClient::~AccessibilityClient()
    {
        if ( m_bInitialized )
        {
            ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );

#ifdef UNLOAD_ON_LAST_CLIENT_DYING
            if( 0 == osl_atomic_decrement( &s_nAccessibilityClients ) )
            {
                s_pFactory = NULL;
                s_pAccessibleFactoryFunc = NULL;
                if ( s_hAccessibleImplementationModule )
                {
                    osl_unloadModule( s_hAccessibleImplementationModule );
                    s_hAccessibleImplementationModule = NULL;
                }
            }
#endif // UNLOAD_ON_LAST_CLIENT_DYING
        }
    }

    IAccessibleFactory& AccessibilityClient::getFactory()
    {
        ensureInitialized();
        OSL_ENSURE( s_pFactory.is(), "AccessibilityClient::getFactory: at least a dummy factory should have been created!" );
        return *s_pFactory;
    }

}   // namespace toolkit

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#708535 Uninitialized scalar field<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <toolkit/helper/accessibilityclient.hxx>
#include <toolkit/helper/accessiblefactory.hxx>
#include <osl/module.h>
#include <osl/diagnose.h>
#include <tools/solar.h>

// #define UNLOAD_ON_LAST_CLIENT_DYING
    // this is not recommended currently. If enabled, the implementation will log
    // the number of active clients, and unload the acc library when the last client
    // goes away.
    // Sounds like a good idea, unfortunately, there's no guarantee that all objects
    // implemented in this library are already dead.
    // Iow, just because an object implementing an XAccessible (implemented in this lib
    // here) died, it's not said that everybody released all references to the
    // XAccessibleContext used by this component, and implemented in the acc lib.
    // So we cannot really unload the lib.

    // Alternatively, if the lib would us own "usage counting", i.e. every component
    // implemented therein would affect a static ref count, the acc lib could care
    // for unloading itself.

namespace toolkit
{

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

    namespace
    {
#ifdef UNLOAD_ON_LAST_CLIENT_DYING
        static oslInterlockedCount                      s_nAccessibilityClients = 0;
#endif // UNLOAD_ON_LAST_CLIENT_DYING
#ifndef DISABLE_DYNLOADING
        static oslModule                                s_hAccessibleImplementationModule = NULL;
#endif
        static GetStandardAccComponentFactory           s_pAccessibleFactoryFunc = NULL;
        static ::rtl::Reference< IAccessibleFactory >   s_pFactory;
    }

    //= AccessibleDummyFactory

    class AccessibleDummyFactory : public IAccessibleFactory
    {
    public:
        AccessibleDummyFactory();

    protected:
        virtual ~AccessibleDummyFactory();

    private:
        AccessibleDummyFactory( const AccessibleDummyFactory& );            // never implemented
        AccessibleDummyFactory& operator=( const AccessibleDummyFactory& ); // never implemented

        oslInterlockedCount m_refCount;

    public:
        // IReference
        virtual oslInterlockedCount SAL_CALL acquire();
        virtual oslInterlockedCount SAL_CALL release();

        // IAccessibleFactory
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXButton* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXCheckBox* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXRadioButton* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXListBox* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXFixedHyperlink* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXFixedText* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXScrollBar* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXEdit* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXComboBox* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXToolBox* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
                createAccessibleContext( VCLXWindow* /*_pXWindow*/ )
        {
            return NULL;
        }
        ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
                createAccessible( Menu* /*_pMenu*/, sal_Bool /*_bIsMenuBar*/ )
        {
            return NULL;
        }
    };

    AccessibleDummyFactory::AccessibleDummyFactory()
        : m_refCount(0)
    {
    }

    AccessibleDummyFactory::~AccessibleDummyFactory()
    {
    }

    oslInterlockedCount SAL_CALL AccessibleDummyFactory::acquire()
    {
        return osl_atomic_increment( &m_refCount );
    }

    oslInterlockedCount SAL_CALL AccessibleDummyFactory::release()
    {
        if ( 0 == osl_atomic_decrement( &m_refCount ) )
        {
            delete this;
            return 0;
        }
        return m_refCount;
    }

    //= AccessibilityClient

    AccessibilityClient::AccessibilityClient()
        :m_bInitialized( false )
    {
    }

#ifndef DISABLE_DYNLOADING
    extern "C" { static void SAL_CALL thisModule() {} }
#else
    extern "C" void *getStandardAccessibleFactory();
#endif

    void AccessibilityClient::ensureInitialized()
    {
        if ( m_bInitialized )
            return;

        ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );

#ifdef UNLOAD_ON_LAST_CLIENT_DYING
        if ( 1 == osl_atomic_increment( &s_nAccessibilityClients ) )
        {   // the first client
#endif // UNLOAD_ON_LAST_CLIENT_DYING
            // load the library implementing the factory
            if ( !s_pFactory.get() )
            {
#ifndef DISABLE_DYNLOADING
                const OUString sModuleName( SVLIBRARY( "acc" ) );
                s_hAccessibleImplementationModule = osl_loadModuleRelative( &thisModule, sModuleName.pData, 0 );
                if ( s_hAccessibleImplementationModule != NULL )
                {
                    const OUString sFactoryCreationFunc =
                        OUString("getStandardAccessibleFactory");
                    s_pAccessibleFactoryFunc = (GetStandardAccComponentFactory)
                        osl_getFunctionSymbol( s_hAccessibleImplementationModule, sFactoryCreationFunc.pData );

                }
                OSL_ENSURE( s_pAccessibleFactoryFunc, "AccessibilityClient::ensureInitialized: could not load the library, or not retrieve the needed symbol!" );
#else
                s_pAccessibleFactoryFunc = getStandardAccessibleFactory;
#endif

                // get a factory instance
                if ( s_pAccessibleFactoryFunc )
                {
                    IAccessibleFactory* pFactory = static_cast< IAccessibleFactory* >( (*s_pAccessibleFactoryFunc)() );
                    OSL_ENSURE( pFactory, "AccessibilityClient::ensureInitialized: no factory provided by the A11Y lib!" );
                    if ( pFactory )
                    {
                        s_pFactory = pFactory;
                        pFactory->release();
                    }
                }
            }

            if ( !s_pFactory.get() )
                // the attempt to load the lib, or to create the factory, failed
                // -> fall back to a dummy factory
                s_pFactory = new AccessibleDummyFactory;
#ifdef UNLOAD_ON_LAST_CLIENT_DYING
        }
#endif

        m_bInitialized = true;
    }

    AccessibilityClient::~AccessibilityClient()
    {
        if ( m_bInitialized )
        {
            ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );

#ifdef UNLOAD_ON_LAST_CLIENT_DYING
            if( 0 == osl_atomic_decrement( &s_nAccessibilityClients ) )
            {
                s_pFactory = NULL;
                s_pAccessibleFactoryFunc = NULL;
                if ( s_hAccessibleImplementationModule )
                {
                    osl_unloadModule( s_hAccessibleImplementationModule );
                    s_hAccessibleImplementationModule = NULL;
                }
            }
#endif // UNLOAD_ON_LAST_CLIENT_DYING
        }
    }

    IAccessibleFactory& AccessibilityClient::getFactory()
    {
        ensureInitialized();
        OSL_ENSURE( s_pFactory.is(), "AccessibilityClient::getFactory: at least a dummy factory should have been created!" );
        return *s_pFactory;
    }

}   // namespace toolkit

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
    The MIT License (MIT)

    Copyright (c) 2014 Anatoli Steinmark

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/

#include <boost/unordered_map.hpp>
#include <boost/assign/list_of.hpp>

#include "../../graphics/Image.hpp"
#include "constants.hpp"

namespace rpgss {
    namespace script {
        namespace graphics_module {

            //---------------------------------------------------------
            bool GetBlendModeConstant(int blend_mode, std::string& out_blend_mode_str)
            {
                typedef boost::unordered_map<int, std::string> map_type;

                static map_type map = boost::assign::map_list_of
                    (graphics::BlendMode::Set,      "set"     )
                    (graphics::BlendMode::Mix,      "mix"     )
                    (graphics::BlendMode::Add,      "add"     )
                    (graphics::BlendMode::Subtract, "subtract")
                    (graphics::BlendMode::Multiply, "multiply");

                map_type::iterator mapped_value = map.find(blend_mode);

                if (mapped_value == map.end()) {
                    return false;
                }

                out_blend_mode_str = mapped_value->second;
                return true;
            }

            //---------------------------------------------------------
            bool GetBlendModeConstant(const std::string& blend_mode_str, int& out_blend_mode)
            {
                typedef boost::unordered_map<std::string, int> map_type;

                static map_type map = boost::assign::map_list_of
                    ("set",      graphics::BlendMode::Set     )
                    ("mix",      graphics::BlendMode::Mix     )
                    ("add",      graphics::BlendMode::Add     )
                    ("subtract", graphics::BlendMode::Subtract)
                    ("multiply", graphics::BlendMode::Multiply);

                map_type::iterator mapped_value = map.find(blend_mode_str);

                if (mapped_value == map.end()) {
                    return false;
                }

                out_blend_mode = mapped_value->second;
                return true;
            }

        } // namespace graphics_module
    } // namespace script
} // namespace rpgss
<commit_msg>Shorten blend mode constants.<commit_after>/*
    The MIT License (MIT)

    Copyright (c) 2014 Anatoli Steinmark

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/

#include <boost/unordered_map.hpp>
#include <boost/assign/list_of.hpp>

#include "../../graphics/Image.hpp"
#include "constants.hpp"

namespace rpgss {
    namespace script {
        namespace graphics_module {

            //---------------------------------------------------------
            bool GetBlendModeConstant(int blend_mode, std::string& out_blend_mode_str)
            {
                typedef boost::unordered_map<int, std::string> map_type;

                static map_type map = boost::assign::map_list_of
                    (graphics::BlendMode::Set,      "set")
                    (graphics::BlendMode::Mix,      "mix")
                    (graphics::BlendMode::Add,      "add")
                    (graphics::BlendMode::Subtract, "sub")
                    (graphics::BlendMode::Multiply, "mul");

                map_type::iterator mapped_value = map.find(blend_mode);

                if (mapped_value == map.end()) {
                    return false;
                }

                out_blend_mode_str = mapped_value->second;
                return true;
            }

            //---------------------------------------------------------
            bool GetBlendModeConstant(const std::string& blend_mode_str, int& out_blend_mode)
            {
                typedef boost::unordered_map<std::string, int> map_type;

                static map_type map = boost::assign::map_list_of
                    ("set", graphics::BlendMode::Set     )
                    ("mix", graphics::BlendMode::Mix     )
                    ("add", graphics::BlendMode::Add     )
                    ("sub", graphics::BlendMode::Subtract)
                    ("mul", graphics::BlendMode::Multiply);

                map_type::iterator mapped_value = map.find(blend_mode_str);

                if (mapped_value == map.end()) {
                    return false;
                }

                out_blend_mode = mapped_value->second;
                return true;
            }

        } // namespace graphics_module
    } // namespace script
} // namespace rpgss
<|endoftext|>


<commit_before>#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

extern "C" {
#include <aes/aes.h>
};

#include <port.hpp>
#include <radio.hpp>
#include <interrupt/PCINT0.hpp>
#include <sensorvalue.hpp>
#include <common.hpp>
#include <packet.hpp>
#include "receiver.hpp"
#include "autoconfig.hpp"

static unsigned short magic;
static aes128_ctx_t aes_ctx;
static void txdata(unsigned char* data, unsigned char len);

void init()
{
	Config config;
	config.read();

	radio::setup();
	radio::setup_basic();

	autoconfig(config);

	radio::select();

	for (auto c = config.radioconfig(); c->reg_ != 0xff; ++c) {
		radio::set(c->reg(), c->value);
	}

	radio::setup_for_rx();

	radio::set(CC1101::IOCFG2, 0x7);
	radio::set(CC1101::IOCFG1, 0x7);

	radio::release();

	magic = config.magic();
	aes128_init(config.key(), &aes_ctx);
}

static void txchr(unsigned char chr)
{
	while (!usart::tx(chr)) {
	}
}

static void txbyte(unsigned char byte)
{
	static const char nibble[] PROGMEM = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
	txchr(pgm_read_byte(&nibble[byte >> 4]));
	txchr(pgm_read_byte(&nibble[byte & 15]));
}

static void txdata(unsigned char* data, unsigned char len)
{
	for (;len > 0; --len) {
		txbyte(*data++);
	}
	txchr('\n');
}

static void receive()
{
	while (radio::USI::DI::is_set()) {
		radio::select();
		unsigned char rxbytes = radio::status(CC1101::RXBYTES);
		if (rxbytes == sizeof(Radiopacket_status)) {
			Radiopacket_status packet;

			radio::read_rxfifo(packet.raw, sizeof(Radiopacket_status));

			aes128_dec(packet.raw, &aes_ctx);

			if (packet.magic != magic) {
				return;
			}

			unsigned char* s = packet.raw + 4;
			unsigned char* e = packet.raw + packet.len;
			char rssi = packet.rssi;
			unsigned char lqi = packet.lqi;
			e += SensorValue<RSSI>::encode(static_cast<int>(rssi) - 148, e);
			e += SensorValue<LQI>::encode(static_cast<int>(lqi & 0x7f), e);

			packet.len = e - s;

			txdata(s, packet.len);
		} else {
			unsigned char d[rxbytes];
			radio::read_rxfifo(d, rxbytes);
		}
	}
}

static void receive_loop()
{
	radio::select();
	radio::wcmd(CC1101::SRX);
	radio::release();
	PCINT0Interrupt::set(receive);

	while(1) {
		set_sleep_mode(SLEEP_MODE_IDLE);
		sleep_mode();
		PCINT0Interrupt::pending();
	}
}

/*{{{ uart */
ISR(USART_RX_vect)
{
	usart::rx_ready();
}

ISR(USART_UDRE_vect)
{
	usart::tx_ready();
}/*}}}*/

int main()
{
	init();

	usart::init();

	PCICR |= _BV(PCIE0);
	PCMSK0 |= _BV(radio::USI::DI::pin);

	sei();

	receive_loop();
}

template<>
usart::rxfifo_t usart::rxfifo = usart::rxfifo_t();
template<>
usart::txfifo_t usart::txfifo = usart::txfifo_t();
<commit_msg>receiver: Sending <cr><lf> after each line<commit_after>#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

extern "C" {
#include <aes/aes.h>
};

#include <port.hpp>
#include <radio.hpp>
#include <interrupt/PCINT0.hpp>
#include <sensorvalue.hpp>
#include <common.hpp>
#include <packet.hpp>
#include "receiver.hpp"
#include "autoconfig.hpp"

static unsigned short magic;
static aes128_ctx_t aes_ctx;
static void txdata(unsigned char* data, unsigned char len);

void init()
{
	Config config;
	config.read();

	radio::setup();
	radio::setup_basic();

	autoconfig(config);

	radio::select();

	for (auto c = config.radioconfig(); c->reg_ != 0xff; ++c) {
		radio::set(c->reg(), c->value);
	}

	radio::setup_for_rx();

	radio::set(CC1101::IOCFG2, 0x7);
	radio::set(CC1101::IOCFG1, 0x7);

	radio::release();

	magic = config.magic();
	aes128_init(config.key(), &aes_ctx);
}

static void txchr(unsigned char chr)
{
	while (!usart::tx(chr)) {
	}
}

static void txbyte(unsigned char byte)
{
	static const char nibble[] PROGMEM = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
	txchr(pgm_read_byte(&nibble[byte >> 4]));
	txchr(pgm_read_byte(&nibble[byte & 15]));
}

static void txdata(unsigned char* data, unsigned char len)
{
	for (;len > 0; --len) {
		txbyte(*data++);
	}
	txchr('\r');
	txchr('\n');
}

static void receive()
{
	while (radio::USI::DI::is_set()) {
		radio::select();
		unsigned char rxbytes = radio::status(CC1101::RXBYTES);
		if (rxbytes == sizeof(Radiopacket_status)) {
			Radiopacket_status packet;

			radio::read_rxfifo(packet.raw, sizeof(Radiopacket_status));

			aes128_dec(packet.raw, &aes_ctx);

			if (packet.magic != magic) {
				return;
			}

			unsigned char* s = packet.raw + 4;
			unsigned char* e = packet.raw + packet.len;
			char rssi = packet.rssi;
			unsigned char lqi = packet.lqi;
			e += SensorValue<RSSI>::encode(static_cast<int>(rssi) - 148, e);
			e += SensorValue<LQI>::encode(static_cast<int>(lqi & 0x7f), e);

			packet.len = e - s;

			txdata(s, packet.len);
		} else {
			unsigned char d[rxbytes];
			radio::read_rxfifo(d, rxbytes);
		}
	}
}

static void receive_loop()
{
	radio::select();
	radio::wcmd(CC1101::SRX);
	radio::release();
	PCINT0Interrupt::set(receive);

	while(1) {
		set_sleep_mode(SLEEP_MODE_IDLE);
		sleep_mode();
		PCINT0Interrupt::pending();
	}
}

/*{{{ uart */
ISR(USART_RX_vect)
{
	usart::rx_ready();
}

ISR(USART_UDRE_vect)
{
	usart::tx_ready();
}/*}}}*/

int main()
{
	init();

	usart::init();

	PCICR |= _BV(PCIE0);
	PCMSK0 |= _BV(radio::USI::DI::pin);

	sei();

	receive_loop();
}

template<>
usart::rxfifo_t usart::rxfifo = usart::rxfifo_t();
template<>
usart::txfifo_t usart::txfifo = usart::txfifo_t();
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef INCLUDED_SW_INC_RING_HXX
#define INCLUDED_SW_INC_RING_HXX

#include <swdllapi.h>
#include <swtypes.hxx>
#include <utility>
#include <iterator>
#include <type_traits>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/intrusive/circular_list_algorithms.hpp>

namespace sw
{
    template <typename value_type> class RingContainer;
    template <typename value_type> class RingIterator;
    /**
     * An intrusive container class double linking the contained nodes
     * @example sw/qa/core/uwriter.cxx
     */
    template <typename value_type>
    class Ring
    {
        public:
            typedef typename std::add_const<value_type>::type const_value_type;
            typedef RingContainer<value_type> ring_container;
            typedef RingContainer<const_value_type> const_ring_container;
            virtual ~Ring()
                { algo::unlink(static_cast< value_type* >(this)); };
            /**
             * Removes this item from its current ring container and adds it to
             * another ring container. If the item was not alone in the original
             * ring container, the other items in the ring will stay in the old
             * ring container.
             * Note: the newly created item will be inserted just before item pDestRing.
             * @param pDestRing the container to add this item to
             */
            void MoveTo( value_type* pDestRing );
            /** @return a stl-like container with begin()/end() for iteration */
            ring_container GetRingContainer();
            /** @return a stl-like container with begin()/end() for const iteration */
            const_ring_container GetRingContainer() const;

        protected:
            /**
             * Creates a new item in a ring container all by itself.
             * Note: Ring instances can newer be outside a container. At most, they
             * are alone in one.
             */
            Ring()
                : pPrev(static_cast< value_type* >(this))
                { algo::init_header(static_cast< value_type* >(this)); }
            /**
             * Creates a new item and add it to an existing ring container.
             * Note: the newly created item will be inserted just before item pRing.
             * @param pRing ring container to add the created item to
             */
            Ring( value_type* pRing );
            /** @return the next item in the ring container */
            value_type* GetNextInRing()
                { return pNext; }
            /** @return the previous item in the ring container */
            value_type* GetPrevInRing()
                { return pPrev; }
            /** @return the next item in the ring container */
            const_value_type* GetNextInRing() const
                { return pNext; }
            /** @return the previous item in the ring container */
            const_value_type* GetPrevInRing() const
                { return pPrev; }
            /** @return true if and only if this item is alone in its ring */
            bool unique() const
                { return algo::unique(static_cast< const_value_type* >(this)); }

        private:
            /** internal implementation class -- not for external use */
            struct Ring_node_traits
            {
                typedef value_type node;
                typedef value_type* node_ptr;
                typedef const value_type* const_node_ptr;
                static node_ptr get_next(const_node_ptr n) { return const_cast<node_ptr>(static_cast<const_node_ptr>(n))->GetNextInRing(); };
                static void set_next(node_ptr n, node_ptr next) { n->pNext = next; };
                static node_ptr get_previous(const_node_ptr n) { return const_cast<node_ptr>(static_cast<const_node_ptr>(n))->GetPrevInRing(); };
                static void set_previous(node_ptr n, node_ptr previous) { n->pPrev = previous; };
            };
            friend ring_container;
            friend const_ring_container;
            friend typename ring_container::iterator;
            friend typename ring_container::const_iterator;
            friend typename const_ring_container::iterator;
            friend typename const_ring_container::const_iterator;
            friend class boost::iterator_core_access;
            typedef boost::intrusive::circular_list_algorithms<Ring_node_traits> algo;
            value_type* pNext;
            value_type* pPrev;
    };

    template <typename value_type>
    inline Ring<value_type>::Ring( value_type* pObj )
        : pPrev(static_cast< value_type* >(this))
    {
        value_type* pThis = static_cast< value_type* >(this);
        if( !pObj )
            algo::init_header(pThis);
        else
            algo::link_before(pObj, pThis);
    }

    template <typename value_type>
    inline void Ring<value_type>::MoveTo(value_type* pDestRing)
    {
        value_type* pThis = static_cast< value_type* >(this);
        // insert into "new"
        if( pDestRing )
        {
            if(algo::unique(pThis))
                algo::link_before(pDestRing, pThis);
            else
                algo::transfer(pDestRing, pThis);
        }
        else
            algo::unlink(pThis);
    }

    /**
     * helper class that provides Svalue_typeL-style container iteration to the ring
     */
    template <typename value_type>
    class RingContainer SAL_FINAL
    {
        private:
            /** the item in the ring where iteration starts */
            value_type* m_pStart;

        public:
            RingContainer( value_type* pRing ) : m_pStart(pRing) {};
            typedef RingIterator<value_type> iterator;
            typedef RingIterator<const value_type> const_iterator;
            /**
             * iterator access
             * @code
             * for(SwPaM& rCurrentPaM : pPaM->GetRingContainer())
             *     do_stuff(rCurrentPaM); // this gets called on every SwPaM in the same ring as pPaM
             * @endcode
             */
            iterator begin();
            iterator end();
            const_iterator begin() const;
            const_iterator end() const;
            /** @return the number of elements in the container */
            size_t size() const
                { return std::distance(begin(), end()); }
            /**
             * Merges two ring containers. All item from both ring containers will
             * be in the same ring container in the end.
             * Note: value_typehe items of this ring container will be inserted just before
             * item pDestRing
             * @param pDestRing the container to merge this container with
             */
            void merge( RingContainer< value_type > aDestRing )
            {
                std::swap(*(&m_pStart->pPrev->pNext), *(&aDestRing.m_pStart->pPrev->pNext));
                std::swap(*(&m_pStart->pPrev), *(&aDestRing.m_pStart->pPrev));
            }
    };

    template <typename value_type>
    class RingIterator SAL_FINAL : public boost::iterator_facade<
          RingIterator<value_type>
        , value_type
        , boost::forward_traversal_tag
        >
    {
        private:
            typedef typename std::remove_const<value_type>::type nonconst_value_type;
        public:
            RingIterator()
                : m_pCurrent(nullptr)
                , m_pStart(nullptr)
            {}
            explicit RingIterator(value_type* pRing, bool bStart = true)
                : m_pCurrent(nullptr)
                , m_pStart(const_cast<nonconst_value_type*>(pRing))
            {
                if(!bStart)
                    m_pCurrent = m_pStart;
            }

        private:
            friend class boost::iterator_core_access;
            void increment()
                { m_pCurrent = m_pCurrent ? m_pCurrent->GetNextInRing() : m_pStart->GetNext(); }
            bool equal(RingIterator const& other) const
            {
                // we never want to compare iterators from
                // different rings or starting points
                assert(m_pStart == other.m_pStart);
                return m_pCurrent == other.m_pCurrent;
            }
            value_type& dereference() const
                { return m_pCurrent ? *m_pCurrent : * m_pStart; }
            /**
             * value_typehis is:
             * - pointing to the current item in the iteration in general
             * - nullptr if on the first item (begin())
             * - m_pStart when beyond the last item (end())
             */
            nonconst_value_type* m_pCurrent;
            /** the first item of the iteration */
            nonconst_value_type* m_pStart;
    };

    template <typename value_type>
    inline typename Ring<value_type>::ring_container Ring<value_type>::GetRingContainer()
        { return Ring<value_type>::ring_container(static_cast< value_type* >(this)); };

    template <typename value_type>
    inline typename Ring<value_type>::const_ring_container Ring<value_type>::GetRingContainer() const
        { return Ring<value_type>::const_ring_container(static_cast< const value_type* >(this)); };

    template <typename value_type>
    inline typename RingContainer<value_type>::iterator RingContainer<value_type>::begin()
        { return RingContainer<value_type>::iterator(m_pStart); };

    template <typename value_type>
    inline typename RingContainer<value_type>::iterator RingContainer<value_type>::end()
        { return RingContainer<value_type>::iterator(m_pStart, false); };

    template <typename value_type>
    inline typename RingContainer<value_type>::const_iterator RingContainer<value_type>::begin() const
        { return RingContainer<value_type>::const_iterator(m_pStart); };

    template <typename value_type>
    inline typename RingContainer<value_type>::const_iterator RingContainer<value_type>::end() const
        { return RingContainer<value_type>::const_iterator(m_pStart, false); };
}
#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>ugly preliminary hack for keeping ggc 4.6 happy<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef INCLUDED_SW_INC_RING_HXX
#define INCLUDED_SW_INC_RING_HXX

#include <swdllapi.h>
#include <swtypes.hxx>
#include <utility>
#include <iterator>
#include <type_traits>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/intrusive/circular_list_algorithms.hpp>

#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)
// gcc 4.6 backwards compat hack, remove ASAP when we drop support
class SwPaM;
class SwViewShell;
class _SaveMergeRedlines;
#endif

namespace sw
{
    template <typename value_type> class RingContainer;
    template <typename value_type> class RingIterator;
    /**
     * An intrusive container class double linking the contained nodes
     * @example sw/qa/core/uwriter.cxx
     */
    template <typename value_type>
    class Ring
    {
        public:
            typedef typename std::add_const<value_type>::type const_value_type;
            typedef RingContainer<value_type> ring_container;
            typedef RingContainer<const_value_type> const_ring_container;
            virtual ~Ring()
                { algo::unlink(static_cast< value_type* >(this)); };
            /**
             * Removes this item from its current ring container and adds it to
             * another ring container. If the item was not alone in the original
             * ring container, the other items in the ring will stay in the old
             * ring container.
             * Note: the newly created item will be inserted just before item pDestRing.
             * @param pDestRing the container to add this item to
             */
            void MoveTo( value_type* pDestRing );
            /** @return a stl-like container with begin()/end() for iteration */
            ring_container GetRingContainer();
            /** @return a stl-like container with begin()/end() for const iteration */
            const_ring_container GetRingContainer() const;

        protected:
            /**
             * Creates a new item in a ring container all by itself.
             * Note: Ring instances can newer be outside a container. At most, they
             * are alone in one.
             */
            Ring()
                : pPrev(static_cast< value_type* >(this))
                { algo::init_header(static_cast< value_type* >(this)); }
            /**
             * Creates a new item and add it to an existing ring container.
             * Note: the newly created item will be inserted just before item pRing.
             * @param pRing ring container to add the created item to
             */
            Ring( value_type* pRing );
            /** @return the next item in the ring container */
            value_type* GetNextInRing()
                { return pNext; }
            /** @return the previous item in the ring container */
            value_type* GetPrevInRing()
                { return pPrev; }
            /** @return the next item in the ring container */
            const_value_type* GetNextInRing() const
                { return pNext; }
            /** @return the previous item in the ring container */
            const_value_type* GetPrevInRing() const
                { return pPrev; }
            /** @return true if and only if this item is alone in its ring */
            bool unique() const
                { return algo::unique(static_cast< const_value_type* >(this)); }

        private:
            /** internal implementation class -- not for external use */
            struct Ring_node_traits
            {
                typedef value_type node;
                typedef value_type* node_ptr;
                typedef const value_type* const_node_ptr;
                static node_ptr get_next(const_node_ptr n) { return const_cast<node_ptr>(static_cast<const_node_ptr>(n))->GetNextInRing(); };
                static void set_next(node_ptr n, node_ptr next) { n->pNext = next; };
                static node_ptr get_previous(const_node_ptr n) { return const_cast<node_ptr>(static_cast<const_node_ptr>(n))->GetPrevInRing(); };
                static void set_previous(node_ptr n, node_ptr previous) { n->pPrev = previous; };
            };
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)
            // gcc 4.6 backwards compat hack, remove ASAP when we drop support
            friend class sw::RingContainer<SwPaM>;
            friend class sw::RingContainer<const SwPaM>;
            friend class sw::RingContainer<SwViewShell>;
            friend class sw::RingContainer<const SwViewShell>;
            friend class sw::RingContainer<_SaveMergeRedlines>;
            friend class sw::RingContainer<const _SaveMergeRedlines>;
#else
            friend ring_container;
            friend const_ring_container;
#endif
            friend typename ring_container::iterator;
            friend typename ring_container::const_iterator;
            friend typename const_ring_container::iterator;
            friend typename const_ring_container::const_iterator;
            friend class boost::iterator_core_access;
            typedef boost::intrusive::circular_list_algorithms<Ring_node_traits> algo;
            value_type* pNext;
            value_type* pPrev;
    };

    template <typename value_type>
    inline Ring<value_type>::Ring( value_type* pObj )
        : pPrev(static_cast< value_type* >(this))
    {
        value_type* pThis = static_cast< value_type* >(this);
        if( !pObj )
            algo::init_header(pThis);
        else
            algo::link_before(pObj, pThis);
    }

    template <typename value_type>
    inline void Ring<value_type>::MoveTo(value_type* pDestRing)
    {
        value_type* pThis = static_cast< value_type* >(this);
        // insert into "new"
        if( pDestRing )
        {
            if(algo::unique(pThis))
                algo::link_before(pDestRing, pThis);
            else
                algo::transfer(pDestRing, pThis);
        }
        else
            algo::unlink(pThis);
    }

    /**
     * helper class that provides Svalue_typeL-style container iteration to the ring
     */
    template <typename value_type>
    class RingContainer SAL_FINAL
    {
        private:
            /** the item in the ring where iteration starts */
            value_type* m_pStart;

        public:
            RingContainer( value_type* pRing ) : m_pStart(pRing) {};
            typedef RingIterator<value_type> iterator;
            typedef RingIterator<const value_type> const_iterator;
            /**
             * iterator access
             * @code
             * for(SwPaM& rCurrentPaM : pPaM->GetRingContainer())
             *     do_stuff(rCurrentPaM); // this gets called on every SwPaM in the same ring as pPaM
             * @endcode
             */
            iterator begin();
            iterator end();
            const_iterator begin() const;
            const_iterator end() const;
            /** @return the number of elements in the container */
            size_t size() const
                { return std::distance(begin(), end()); }
            /**
             * Merges two ring containers. All item from both ring containers will
             * be in the same ring container in the end.
             * Note: value_typehe items of this ring container will be inserted just before
             * item pDestRing
             * @param pDestRing the container to merge this container with
             */
            void merge( RingContainer< value_type > aDestRing )
            {
                std::swap(*(&m_pStart->pPrev->pNext), *(&aDestRing.m_pStart->pPrev->pNext));
                std::swap(*(&m_pStart->pPrev), *(&aDestRing.m_pStart->pPrev));
            }
    };

    template <typename value_type>
    class RingIterator SAL_FINAL : public boost::iterator_facade<
          RingIterator<value_type>
        , value_type
        , boost::forward_traversal_tag
        >
    {
        private:
            typedef typename std::remove_const<value_type>::type nonconst_value_type;
        public:
            RingIterator()
                : m_pCurrent(nullptr)
                , m_pStart(nullptr)
            {}
            explicit RingIterator(value_type* pRing, bool bStart = true)
                : m_pCurrent(nullptr)
                , m_pStart(const_cast<nonconst_value_type*>(pRing))
            {
                if(!bStart)
                    m_pCurrent = m_pStart;
            }

        private:
            friend class boost::iterator_core_access;
            void increment()
                { m_pCurrent = m_pCurrent ? m_pCurrent->GetNextInRing() : m_pStart->GetNext(); }
            bool equal(RingIterator const& other) const
            {
                // we never want to compare iterators from
                // different rings or starting points
                assert(m_pStart == other.m_pStart);
                return m_pCurrent == other.m_pCurrent;
            }
            value_type& dereference() const
                { return m_pCurrent ? *m_pCurrent : * m_pStart; }
            /**
             * value_typehis is:
             * - pointing to the current item in the iteration in general
             * - nullptr if on the first item (begin())
             * - m_pStart when beyond the last item (end())
             */
            nonconst_value_type* m_pCurrent;
            /** the first item of the iteration */
            nonconst_value_type* m_pStart;
    };

    template <typename value_type>
    inline typename Ring<value_type>::ring_container Ring<value_type>::GetRingContainer()
        { return Ring<value_type>::ring_container(static_cast< value_type* >(this)); };

    template <typename value_type>
    inline typename Ring<value_type>::const_ring_container Ring<value_type>::GetRingContainer() const
        { return Ring<value_type>::const_ring_container(static_cast< const value_type* >(this)); };

    template <typename value_type>
    inline typename RingContainer<value_type>::iterator RingContainer<value_type>::begin()
        { return RingContainer<value_type>::iterator(m_pStart); };

    template <typename value_type>
    inline typename RingContainer<value_type>::iterator RingContainer<value_type>::end()
        { return RingContainer<value_type>::iterator(m_pStart, false); };

    template <typename value_type>
    inline typename RingContainer<value_type>::const_iterator RingContainer<value_type>::begin() const
        { return RingContainer<value_type>::const_iterator(m_pStart); };

    template <typename value_type>
    inline typename RingContainer<value_type>::const_iterator RingContainer<value_type>::end() const
        { return RingContainer<value_type>::const_iterator(m_pStart, false); };
}
#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
 * Author: Rafael Neri <rafael.neri@gmail.com>
 * Copyright (c) 2014-2015 Intel Corporation.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <iostream>
#include <string>
#include <stdexcept>
#include <unistd.h>
#include <stdlib.h>
#include <functional>

#include "hcsr04.h"

using namespace upm;

#ifdef JAVACALLBACK
HCSR04::HCSR04 (uint8_t triggerPin, uint8_t echoPin, IsrCallback *cb)
{
        HCSR04 (triggerPin, echoPin, generic_callback_isr);
}
#endif

HCSR04::HCSR04 (uint8_t triggerPin, uint8_t echoPin, void (*fptr)(void *)) {
    mraa_result_t error  = MRAA_SUCCESS;
    m_name              = "HCSR04";

    m_triggerPinCtx     = mraa_gpio_init (triggerPin);
    if (m_triggerPinCtx == NULL) {
        throw std::invalid_argument(std::string(__FUNCTION__) +
                                    ": mraa_pwm_init() failed, invalid pin?");
        return;
    }

    mraa_gpio_dir(m_triggerPinCtx, MRAA_GPIO_OUT);
    mraa_gpio_write (m_triggerPinCtx, 0);

    m_echoPinCtx = mraa_gpio_init(echoPin);
    if (m_echoPinCtx == NULL) {
        throw std::invalid_argument(std::string(__FUNCTION__) +
                                    ": mraa_gpio_init() failed, invalid pin?");
        return;
    }

    mraa_gpio_dir(m_echoPinCtx, MRAA_GPIO_IN);
    mraa_gpio_isr(m_echoPinCtx, MRAA_GPIO_EDGE_BOTH, fptr, NULL);
}

HCSR04::~HCSR04 () {
    mraa_result_t error = MRAA_SUCCESS;

    error = mraa_gpio_close (m_triggerPinCtx);
    if (error != MRAA_SUCCESS) {
        mraa_result_print (error);
    }

    error = mraa_gpio_close (m_echoPinCtx);
    if (error != MRAA_SUCCESS) {
        mraa_result_print (error);
    }
}

double
HCSR04::timing() {
    mraa_gpio_write (m_triggerPinCtx, 1);
    usleep(10);
    mraa_gpio_write (m_triggerPinCtx, 0);

    m_doWork = 0;
    m_InterruptCounter = 0;
    while (!m_doWork) {
        usleep (5);
    }

    return m_FallingTimeStamp - m_RisingTimeStamp;
}

void
HCSR04::ackEdgeDetected () {
    struct timeval timer;
    gettimeofday(&timer, NULL);

    ++m_InterruptCounter;
    if (!(m_InterruptCounter % 2)) {
        m_FallingTimeStamp  = 1000000 * timer.tv_sec + timer.tv_usec;
        m_doWork = 1;
    } else {
        m_RisingTimeStamp = 1000000 * timer.tv_sec + timer.tv_usec;
    }
}

double
HCSR04::getDistance(int sys)
{
    double _timing = timing();
    if (sys)
    {
        return (_timing/2) / 29.1;
    } else {
        return (_timing/2) / 74.1;
    }
}
<commit_msg>hcsr04: Pass reference to current object to ISR.<commit_after>/*
 * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
 * Author: Rafael Neri <rafael.neri@gmail.com>
 * Copyright (c) 2014-2015 Intel Corporation.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <iostream>
#include <string>
#include <stdexcept>
#include <unistd.h>
#include <stdlib.h>
#include <functional>

#include "hcsr04.h"

using namespace upm;

#ifdef JAVACALLBACK
HCSR04::HCSR04 (uint8_t triggerPin, uint8_t echoPin, IsrCallback *cb)
{
        HCSR04 (triggerPin, echoPin, generic_callback_isr);
}
#endif

HCSR04::HCSR04 (uint8_t triggerPin, uint8_t echoPin, void (*fptr)(void *)) {
    mraa_result_t error  = MRAA_SUCCESS;
    m_name              = "HCSR04";

    m_triggerPinCtx     = mraa_gpio_init (triggerPin);
    if (m_triggerPinCtx == NULL) {
        throw std::invalid_argument(std::string(__FUNCTION__) +
                                    ": mraa_pwm_init() failed, invalid pin?");
        return;
    }

    mraa_gpio_dir(m_triggerPinCtx, MRAA_GPIO_OUT);
    mraa_gpio_write (m_triggerPinCtx, 0);

    m_echoPinCtx = mraa_gpio_init(echoPin);
    if (m_echoPinCtx == NULL) {
        throw std::invalid_argument(std::string(__FUNCTION__) +
                                    ": mraa_gpio_init() failed, invalid pin?");
        return;
    }

    mraa_gpio_dir(m_echoPinCtx, MRAA_GPIO_IN);
    mraa_gpio_isr(m_echoPinCtx, MRAA_GPIO_EDGE_BOTH, fptr, (void*)this);
}

HCSR04::~HCSR04 () {
    mraa_result_t error = MRAA_SUCCESS;

    error = mraa_gpio_close (m_triggerPinCtx);
    if (error != MRAA_SUCCESS) {
        mraa_result_print (error);
    }

    error = mraa_gpio_close (m_echoPinCtx);
    if (error != MRAA_SUCCESS) {
        mraa_result_print (error);
    }
}

double
HCSR04::timing() {
    mraa_gpio_write (m_triggerPinCtx, 1);
    usleep(10);
    mraa_gpio_write (m_triggerPinCtx, 0);

    m_doWork = 0;
    m_InterruptCounter = 0;
    while (!m_doWork) {
        usleep (5);
    }

    return m_FallingTimeStamp - m_RisingTimeStamp;
}

void
HCSR04::ackEdgeDetected () {
    struct timeval timer;
    gettimeofday(&timer, NULL);

    ++m_InterruptCounter;
    if (!(m_InterruptCounter % 2)) {
        m_FallingTimeStamp  = 1000000 * timer.tv_sec + timer.tv_usec;
        m_doWork = 1;
    } else {
        m_RisingTimeStamp = 1000000 * timer.tv_sec + timer.tv_usec;
    }
}

double
HCSR04::getDistance(int sys)
{
    double _timing = timing();
    if (sys)
    {
        return (_timing/2) / 29.1;
    } else {
        return (_timing/2) / 74.1;
    }
}
<|endoftext|>


<commit_before>#include "MoscowDiscoAnimation.h"
#include <stdlib.h>
#include <Arduino.h>

void MoscowDiscoAnimation::drawFrame() {
    unsigned int leds = getTotalLeds();
    for (int led = 0 ; led < leds ; led++) {
        digitalWrite(led, HIGH);
    }
    delay(50);
    for (int led = 0 ; led < leds ; led++) {
        digitalWrite(led, LOW);
    }
};
<commit_msg>Fix MoscowDiscoAnimation final delay<commit_after>#include "MoscowDiscoAnimation.h"
#include <stdlib.h>
#include <Arduino.h>

void MoscowDiscoAnimation::drawFrame() {
    unsigned int leds = getTotalLeds();
    for (int led = 0 ; led < leds ; led++) {
        digitalWrite(led, HIGH);
    }
    delay(50);
    for (int led = 0 ; led < leds ; led++) {
        digitalWrite(led, LOW);
    }
    delay(50);
};
<|endoftext|>


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

#include "Application.h"
#include "Console.h"
#include "DebugHud.h"
#include "Engine.h"
#include "InputEvents.h"
#include "Renderer.h"
#include "ResourceCache.h"
#include "Sprite.h"
#include "Texture2D.h"
#include "UI.h"
#include "XMLFile.h"

Sample::Sample(Context* context) :
    Application(context)
{
}

void Sample::Setup()
{
    // Modify engine startup parameters
    engineParameters_["WindowTitle"] = GetTypeName();
    engineParameters_["LogName"]     = GetTypeName() + ".log";
    engineParameters_["FullScreen"]  = false;
    engineParameters_["Headless"]    = false;
}

void Sample::Start()
{
    // Create logo
    CreateLogo();

    // Create console and debug HUD
    CreateConsoleAndDebugHud();

    // Subscribe key down event
    SubscribeToEvent(E_KEYDOWN, HANDLER(Sample, HandleKeyDown));
}

void Sample::SetLogoVisible(bool enable)
{
    if (logoSprite_)
        logoSprite_->SetVisible(enable);
}

void Sample::CreateLogo()
{
    // Get logo texture
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    Texture2D* logoTexture = cache->GetResource<Texture2D>("Textures/LogoLarge.png");
    if (!logoTexture)
        return;

    // Create logo sprite and add to the UI layout
    UI* ui = GetSubsystem<UI>();
    logoSprite_ = ui->GetRoot()->CreateChild<Sprite>();

    // Set logo sprite texture
    logoSprite_->SetTexture(logoTexture);

    int textureWidth = logoTexture->GetWidth();
    int textureHeight = logoTexture->GetHeight();

    // Set logo sprite scale
    logoSprite_->SetScale(256.0f / textureWidth);

    // Set logo sprite size
    logoSprite_->SetSize(textureWidth, textureHeight);

    // Set logo sprite hot spot
    logoSprite_->SetHotSpot(0, textureHeight);

    // Set logo sprite alignment
    logoSprite_->SetAlignment(HA_LEFT, VA_BOTTOM);

    // Make logo not fully opaque to show the scene underneath
    logoSprite_->SetOpacity(0.75f);

    // Set a low priority for the logo so that other UI elements can be drawn on top
    logoSprite_->SetPriority(-100);
}

void Sample::CreateConsoleAndDebugHud()
{
    // Get default style
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    XMLFile* xmlFile = cache->GetResource<XMLFile>("UI/DefaultStyle.xml");

    // Create console
    Console* console = engine_->CreateConsole();
    console->SetDefaultStyle(xmlFile);

    // Create debug HUD.
    DebugHud* debugHud = engine_->CreateDebugHud();
    debugHud->SetDefaultStyle(xmlFile);
}

void Sample::HandleKeyDown(StringHash eventType, VariantMap& eventData)
{
    using namespace KeyDown;

    int key = eventData[P_KEY].GetInt();

    // Close console (if open) or exit when ESC is pressed
    if (key == KEY_ESC)
    {
        Console* console = GetSubsystem<Console>();
        if (!console->IsVisible())
            engine_->Exit();
        else
            console->SetVisible(false);
    }

    // Toggle console with F1
    else if (key == KEY_F1)
        GetSubsystem<Console>()->Toggle();

    // Toggle debug HUD with F2
    else if (key == KEY_F2)
        GetSubsystem<DebugHud>()->ToggleAll();

    // Common rendering quality controls, only when UI has no focused element
    else if (!GetSubsystem<UI>()->GetFocusElement())
    {
        Renderer* renderer = GetSubsystem<Renderer>();

        // Texture quality
        if (key == '1')
        {
            int quality = renderer->GetTextureQuality();
            ++quality;
            if (quality > QUALITY_HIGH)
                quality = QUALITY_LOW;
            renderer->SetTextureQuality(quality);
        }

        // Material quality
        else if (key == '2')
        {
            int quality = renderer->GetMaterialQuality();
            ++quality;
            if (quality > QUALITY_HIGH)
                quality = QUALITY_LOW;
            renderer->SetMaterialQuality(quality);
        }

        // Specular lighting
        else if (key == '3')
            renderer->SetSpecularLighting(!renderer->GetSpecularLighting());

        // Shadow rendering
        else if (key == '4')
            renderer->SetDrawShadows(!renderer->GetDrawShadows());

        // Shadow map resolution
        else if (key == '5')
        {
            int shadowMapSize = renderer->GetShadowMapSize();
            shadowMapSize *= 2;
            if (shadowMapSize > 2048)
                shadowMapSize = 512;
            renderer->SetShadowMapSize(shadowMapSize);
        }

        // Shadow depth and filtering quality
        else if (key == '6')
        {
            int quality = renderer->GetShadowQuality();
            ++quality;
            if (quality > SHADOWQUALITY_HIGH_24BIT)
                quality = SHADOWQUALITY_LOW_16BIT;
            renderer->SetShadowQuality(quality);
        }

        // Occlusion culling
        else if (key == '7')
        {
            bool occlusion = renderer->GetMaxOccluderTriangles() > 0;
            occlusion = !occlusion;
            renderer->SetMaxOccluderTriangles(occlusion ? 5000 : 0);
        }

        // Instancing
        else if (key == '8')
            renderer->SetDynamicInstancing(!renderer->GetDynamicInstancing());
    }
}
<commit_msg>Extended Sample with ability to set window title and icon and take screenshots<commit_after>//
// Copyright (c) 2008-2014 the Urho3D project.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#include "Application.h"
#include "Console.h"
#include "DebugHud.h"
#include "Engine.h"
#include "Graphics.h"
#include "InputEvents.h"
#include "Renderer.h"
#include "ResourceCache.h"
#include "Sprite.h"
#include "Texture2D.h"
#include "Timer.h"
#include "UI.h"
#include "XMLFile.h"

Sample::Sample(Context* context) :
    Application(context)
{
}

void Sample::Setup()
{
    // Modify engine startup parameters
    engineParameters_["WindowTitle"] = GetTypeName();
    engineParameters_["LogName"]     = GetTypeName() + ".log";
    engineParameters_["FullScreen"]  = false;
    engineParameters_["Headless"]    = false;
}

void Sample::Start()
{
    // Create logo
    CreateLogo();

    // Set custom window Title & Icon
    SetWindowTitleAndIcon();

    // Create console and debug HUD
    CreateConsoleAndDebugHud();

    // Subscribe key down event
    SubscribeToEvent(E_KEYDOWN, HANDLER(Sample, HandleKeyDown));
}

void Sample::SetLogoVisible(bool enable)
{
    if (logoSprite_)
        logoSprite_->SetVisible(enable);
}

void Sample::CreateLogo()
{
    // Get logo texture
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    Texture2D* logoTexture = cache->GetResource<Texture2D>("Textures/LogoLarge.png");
    if (!logoTexture)
        return;

    // Create logo sprite and add to the UI layout
    UI* ui = GetSubsystem<UI>();
    logoSprite_ = ui->GetRoot()->CreateChild<Sprite>();

    // Set logo sprite texture
    logoSprite_->SetTexture(logoTexture);

    int textureWidth = logoTexture->GetWidth();
    int textureHeight = logoTexture->GetHeight();

    // Set logo sprite scale
    logoSprite_->SetScale(256.0f / textureWidth);

    // Set logo sprite size
    logoSprite_->SetSize(textureWidth, textureHeight);

    // Set logo sprite hot spot
    logoSprite_->SetHotSpot(0, textureHeight);

    // Set logo sprite alignment
    logoSprite_->SetAlignment(HA_LEFT, VA_BOTTOM);

    // Make logo not fully opaque to show the scene underneath
    logoSprite_->SetOpacity(0.75f);

    // Set a low priority for the logo so that other UI elements can be drawn on top
    logoSprite_->SetPriority(-100);
}

void Sample::SetWindowTitleAndIcon()
{
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    Graphics* graphics = GetSubsystem<Graphics>();
    Image* icon = cache->GetResource<Image>("Textures/LogoLarge.png");
    graphics->SetWindowIcon(icon);
    graphics->SetWindowTitle("Urho3D Sample");
}

void Sample::CreateConsoleAndDebugHud()
{
    // Get default style
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    XMLFile* xmlFile = cache->GetResource<XMLFile>("UI/DefaultStyle.xml");

    // Create console
    Console* console = engine_->CreateConsole();
    console->SetDefaultStyle(xmlFile);

    // Create debug HUD.
    DebugHud* debugHud = engine_->CreateDebugHud();
    debugHud->SetDefaultStyle(xmlFile);
}

void Sample::HandleKeyDown(StringHash eventType, VariantMap& eventData)
{
    using namespace KeyDown;

    int key = eventData[P_KEY].GetInt();

    // Close console (if open) or exit when ESC is pressed
    if (key == KEY_ESC)
    {
        Console* console = GetSubsystem<Console>();
        if (!console->IsVisible())
            engine_->Exit();
        else
            console->SetVisible(false);
    }

    // Toggle console with F1
    else if (key == KEY_F1)
        GetSubsystem<Console>()->Toggle();

    // Toggle debug HUD with F2
    else if (key == KEY_F2)
        GetSubsystem<DebugHud>()->ToggleAll();

    // Common rendering quality controls, only when UI has no focused element
    else if (!GetSubsystem<UI>()->GetFocusElement())
    {
        Renderer* renderer = GetSubsystem<Renderer>();

        // Texture quality
        if (key == '1')
        {
            int quality = renderer->GetTextureQuality();
            ++quality;
            if (quality > QUALITY_HIGH)
                quality = QUALITY_LOW;
            renderer->SetTextureQuality(quality);
        }

        // Material quality
        else if (key == '2')
        {
            int quality = renderer->GetMaterialQuality();
            ++quality;
            if (quality > QUALITY_HIGH)
                quality = QUALITY_LOW;
            renderer->SetMaterialQuality(quality);
        }

        // Specular lighting
        else if (key == '3')
            renderer->SetSpecularLighting(!renderer->GetSpecularLighting());

        // Shadow rendering
        else if (key == '4')
            renderer->SetDrawShadows(!renderer->GetDrawShadows());

        // Shadow map resolution
        else if (key == '5')
        {
            int shadowMapSize = renderer->GetShadowMapSize();
            shadowMapSize *= 2;
            if (shadowMapSize > 2048)
                shadowMapSize = 512;
            renderer->SetShadowMapSize(shadowMapSize);
        }

        // Shadow depth and filtering quality
        else if (key == '6')
        {
            int quality = renderer->GetShadowQuality();
            ++quality;
            if (quality > SHADOWQUALITY_HIGH_24BIT)
                quality = SHADOWQUALITY_LOW_16BIT;
            renderer->SetShadowQuality(quality);
        }

        // Occlusion culling
        else if (key == '7')
        {
            bool occlusion = renderer->GetMaxOccluderTriangles() > 0;
            occlusion = !occlusion;
            renderer->SetMaxOccluderTriangles(occlusion ? 5000 : 0);
        }

        // Instancing
        else if (key == '8')
            renderer->SetDynamicInstancing(!renderer->GetDynamicInstancing());

        // Take screenshot
        else if (key == '9')
        {
            Graphics* graphics = GetSubsystem<Graphics>();
            Image screenshot(context_);
            graphics->TakeScreenShot(screenshot);
            screenshot.FlipVertical();
            screenshot.SavePNG("Data/" + Time::GetTimeStamp() + "Screenshot.png"); // Here we save in the Data folder with date and time appended
	    }
    }
}
<|endoftext|>


<commit_before>#include "TextureLoaderTGA.h"

#include <Render/Texture.h>
#include <Render/GPUDriver.h>
#include <IO/BinaryReader.h>
#include <Core/Factory.h>

// Supports loading of TrueColor images only. //???support black-and-white too? RLE?
// Only a required subset is implemented, in accordance with a specification at:
//http://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf

namespace Resources
{
__ImplementClass(Resources::CTextureLoaderTGA, 'TGAL', Resources::CTextureLoader);

#pragma pack(push, 1)

struct CTGAHeader
{
	U8	IDLength;
	U8	ColorMapType;
	U8	ImageType;
	U8	ColorMapSpecUnusedPart[5];
	U8	ImageSpecUnusedPart[4];
	U16	ImageWidth;
	U16	ImageHeight;
	U8	BitsPerPixel;
	U8	ImageDescriptor;
};

struct CTGAFooter
{
	U32	ExtensionAreaOffset;
	U32	DeveloperDirOffset;
	U8	Signature[18];
};

#pragma pack(pop)

// For CTGAHeader.ImageDescriptor bit checking
#define TGA_RIGHT_TO_LEFT	(1 << 4)
#define TGA_TOP_TO_BOTTOM	(1 << 5)
#define TGA_ATTRIBUTE_BITS	0x0f

const char ReferenceSignature[] = "TRUEVISION-XFILE";

const Core::CRTTI& CTextureLoaderTGA::GetResultType() const
{
	return Render::CTexture::RTTI;
}
//---------------------------------------------------------------------

PResourceObject CTextureLoaderTGA::Load(IO::CStream& Stream)
{
	if (GPU.IsNullPtr()) return NULL;

	IO::CBinaryReader Reader(Stream);

	CTGAHeader Header;
	if (!Reader.Read(Header)) return NULL;

	// Only 32-bit TrueColor compressed and uncompressed images are supported for now
	if (Header.ImageType != 2 && Header.ImageType != 10) return NULL;

	const bool IsRLECompressed = (Header.ImageType == 10);

	if (!Stream.Seek(26, IO::Seek_End)) return NULL;
	CTGAFooter Footer;
	if (!Reader.Read(Footer)) return NULL;

	bool HasAlpha;
	if (!memcmp(Footer.Signature, ReferenceSignature, sizeof(ReferenceSignature) - 1))
	{
		// New TGA
		if (Footer.ExtensionAreaOffset)
		{
			if (!Stream.Seek(Footer.ExtensionAreaOffset + 494, IO::Seek_Begin)) return NULL;

			U8 AttributesType;
			if (!Reader.Read(AttributesType)) return NULL;

			HasAlpha = (AttributesType == 3 || AttributesType == 4);
			//!!!???AttributesType == 4 is a premultiplied alpha. How to handle?
		}
		else HasAlpha = !!(Header.ImageDescriptor & TGA_ATTRIBUTE_BITS);
	}
	else
	{
		// Original TGA
		HasAlpha = !!(Header.ImageDescriptor & TGA_ATTRIBUTE_BITS);
	}

	Render::CTextureDesc TexDesc;
	TexDesc.Type = Render::Texture_2D;
	TexDesc.Width = Header.ImageWidth;
	TexDesc.Height = Header.ImageHeight;
	TexDesc.Depth = 1;
	TexDesc.ArraySize = 1;
	TexDesc.MipLevels = 1; //!!!set DesiredMipCount, if provided! some value for 'as in file', some for 'full chain'
	TexDesc.MSAAQuality = Render::MSAA_None;

	switch (Header.BitsPerPixel)
	{
		case 32:
			TexDesc.Format = HasAlpha ? Render::PixelFmt_B8G8R8A8 : Render::PixelFmt_B8G8R8X8;
			break;
		//???D3D11 24-bit support?
		//case 8:
		//	TexDesc.Format = greyscale;
		//	break;
		default:
			return NULL;
	}

	if (!Stream.Seek(sizeof(Header) + Header.IDLength, IO::Seek_Begin)) return NULL;

	U8* pData = NULL;
	bool Mapped;
	if (IsRLECompressed)
	{
		Mapped = false;
		UPTR DataSize = (Header.ImageWidth * Header.ImageHeight * Header.BitsPerPixel) >> 3;
		pData = (U8*)n_malloc(DataSize);
		U8* pCurrPixel = pData;
		const U8* pDataEnd = pData + DataSize;

		UPTR BytesPerPixel = Header.BitsPerPixel >> 3;
		n_assert_dbg(BytesPerPixel <= 4); // We never expect TGA with more than 32 bpp
		while (pCurrPixel < pDataEnd)
		{
			U8 ChunkHeader;
			if (Stream.Read(&ChunkHeader, sizeof(U8)) != sizeof(U8))
			{
				n_free(pData);
				return NULL;
			}

			if (ChunkHeader & 0x80)
			{
				// RLE
				U32 PixelValue;
				if (Stream.Read(&PixelValue, BytesPerPixel) != BytesPerPixel)
				{
					n_free(pData);
					return NULL;
				}

				const U8 ChunkPixelCount = ChunkHeader - 127; // (ChunkHeader & 0x7f) + 1
				if (BytesPerPixel == 4)
				{
					const U8* pChunkEnd = pCurrPixel + BytesPerPixel * ChunkPixelCount;
					while (pCurrPixel < pChunkEnd)
					{
						*((U32*)pCurrPixel) = PixelValue;
						pCurrPixel += BytesPerPixel;
					}
				}
				else
				{
					const U8* pChunkEnd = pCurrPixel + BytesPerPixel * ChunkPixelCount;
					while (pCurrPixel < pChunkEnd)
					{
						pCurrPixel[0] = ((U8*)&PixelValue)[0];
						if (BytesPerPixel > 1) pCurrPixel[1] = ((U8*)&PixelValue)[1];
						if (BytesPerPixel > 2) pCurrPixel[2] = ((U8*)&PixelValue)[2];
						pCurrPixel += BytesPerPixel;
					}
				}
			}
			else
			{
				// Raw
				const U8 ChunkPixelCount = ChunkHeader + 1;
				const UPTR ChunkSize = BytesPerPixel * ChunkPixelCount;
				if (Stream.Read(pCurrPixel, ChunkSize) != ChunkSize)
				{
					n_free(pData);
					return NULL;
				}
				pCurrPixel += ChunkSize;
			}
		}
	}
	else
	{
		if (Stream.CanBeMapped()) pData = (U8*)Stream.Map();
		Mapped = !!pData;
		if (!Mapped)
		{
			UPTR DataSize = (Header.ImageWidth * Header.ImageHeight * Header.BitsPerPixel) >> 3;
			pData = (U8*)n_malloc(DataSize);
			if (Stream.Read(pData, DataSize) != DataSize)
			{
				n_free(pData);
				return NULL;
			}
		}
	}

	Render::PTexture Texture = GPU->CreateTexture(TexDesc, Render::Access_GPU_Read, pData, false);

	if (Mapped) Stream.Unmap();
	else n_free(pData);

	return Texture.GetUnsafe();
}
//---------------------------------------------------------------------

}<commit_msg>24-bit compressed and uncompressed TGA loading added<commit_after>#include "TextureLoaderTGA.h"

#include <Render/Texture.h>
#include <Render/GPUDriver.h>
#include <IO/BinaryReader.h>
#include <Core/Factory.h>

// Supports loading of TrueColor images only. //???support black-and-white too? RLE?
// Only a required subset is implemented, in accordance with a specification at:
//http://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf

namespace Resources
{
__ImplementClass(Resources::CTextureLoaderTGA, 'TGAL', Resources::CTextureLoader);

#pragma pack(push, 1)

struct CTGAHeader
{
	U8	IDLength;
	U8	ColorMapType;
	U8	ImageType;
	U8	ColorMapSpecUnusedPart[5];
	U8	ImageSpecUnusedPart[4];
	U16	ImageWidth;
	U16	ImageHeight;
	U8	BitsPerPixel;
	U8	ImageDescriptor;
};

struct CTGAFooter
{
	U32	ExtensionAreaOffset;
	U32	DeveloperDirOffset;
	U8	Signature[18];
};

#pragma pack(pop)

// For CTGAHeader.ImageDescriptor bit checking
#define TGA_RIGHT_TO_LEFT	(1 << 4)
#define TGA_TOP_TO_BOTTOM	(1 << 5)
#define TGA_ATTRIBUTE_BITS	0x0f

const char ReferenceSignature[] = "TRUEVISION-XFILE";

const Core::CRTTI& CTextureLoaderTGA::GetResultType() const
{
	return Render::CTexture::RTTI;
}
//---------------------------------------------------------------------

PResourceObject CTextureLoaderTGA::Load(IO::CStream& Stream)
{
	if (GPU.IsNullPtr()) return NULL;

	IO::CBinaryReader Reader(Stream);

	CTGAHeader Header;
	if (!Reader.Read(Header)) return NULL;

	// Only 32-bit TrueColor compressed and uncompressed images are supported for now
	if (Header.ImageType != 2 && Header.ImageType != 10) return NULL;

	const bool IsRLECompressed = (Header.ImageType == 10);

	if (!Stream.Seek(26, IO::Seek_End)) return NULL;
	CTGAFooter Footer;
	if (!Reader.Read(Footer)) return NULL;

	bool HasAlpha;
	if (!memcmp(Footer.Signature, ReferenceSignature, sizeof(ReferenceSignature) - 1))
	{
		// New TGA
		if (Footer.ExtensionAreaOffset)
		{
			if (!Stream.Seek(Footer.ExtensionAreaOffset + 494, IO::Seek_Begin)) return NULL;

			U8 AttributesType;
			if (!Reader.Read(AttributesType)) return NULL;

			HasAlpha = (AttributesType == 3 || AttributesType == 4);
			//!!!???AttributesType == 4 is a premultiplied alpha. How to handle?
		}
		else HasAlpha = !!(Header.ImageDescriptor & TGA_ATTRIBUTE_BITS);
	}
	else
	{
		// Original TGA
		HasAlpha = !!(Header.ImageDescriptor & TGA_ATTRIBUTE_BITS);
	}

	Render::CTextureDesc TexDesc;
	TexDesc.Type = Render::Texture_2D;
	TexDesc.Width = Header.ImageWidth;
	TexDesc.Height = Header.ImageHeight;
	TexDesc.Depth = 1;
	TexDesc.ArraySize = 1;
	TexDesc.MipLevels = 1; //!!!set DesiredMipCount, if provided! some value for 'as in file', some for 'full chain'
	TexDesc.MSAAQuality = Render::MSAA_None;

	UPTR BytesPerTargetPixel;
	switch (Header.BitsPerPixel)
	{
		case 32:
			TexDesc.Format = HasAlpha ? Render::PixelFmt_B8G8R8A8 : Render::PixelFmt_B8G8R8X8;
			BytesPerTargetPixel = 4;
			break;
		case 24:
			TexDesc.Format = Render::PixelFmt_B8G8R8X8;
			BytesPerTargetPixel = 4;
			break;
		//case 8:
		//	TexDesc.Format = greyscale;
		//	break;
		default:
			return NULL;
	}

	UPTR BytesPerPixel = Header.BitsPerPixel >> 3;
	n_assert_dbg(BytesPerPixel <= BytesPerTargetPixel);

	if (!Stream.Seek(sizeof(Header) + Header.IDLength, IO::Seek_Begin)) return NULL;

	U8* pData = NULL;
	bool Mapped;
	if (IsRLECompressed)
	{
		Mapped = false;
		UPTR DataSize = Header.ImageWidth * Header.ImageHeight * BytesPerTargetPixel;
		pData = (U8*)n_malloc(DataSize);
		U8* pCurrPixel = pData;
		const U8* pDataEnd = pData + DataSize;

		n_assert_dbg(BytesPerPixel <= 4); // We never expect TGA with more than 32 bpp
		while (pCurrPixel < pDataEnd)
		{
			U8 ChunkHeader;
			if (Stream.Read(&ChunkHeader, sizeof(U8)) != sizeof(U8))
			{
				n_free(pData);
				return NULL;
			}

			if (ChunkHeader & 0x80)
			{
				// RLE
				U32 PixelValue;
				if (Stream.Read(&PixelValue, BytesPerPixel) != BytesPerPixel)
				{
					n_free(pData);
					return NULL;
				}

				const U8 ChunkPixelCount = ChunkHeader - 127; // (ChunkHeader & 0x7f) + 1
				if (BytesPerPixel == 4)
				{
					const U8* pChunkEnd = pCurrPixel + BytesPerTargetPixel * ChunkPixelCount;
					while (pCurrPixel < pChunkEnd)
					{
						*((U32*)pCurrPixel) = PixelValue;
						pCurrPixel += BytesPerTargetPixel;
					}
				}
				else
				{
					const U8* pChunkEnd = pCurrPixel + BytesPerTargetPixel * ChunkPixelCount;
					while (pCurrPixel < pChunkEnd)
					{
						pCurrPixel[0] = ((U8*)&PixelValue)[0];
						if (BytesPerPixel > 1) pCurrPixel[1] = ((U8*)&PixelValue)[1];
						if (BytesPerPixel > 2) pCurrPixel[2] = ((U8*)&PixelValue)[2];
						if (BytesPerTargetPixel > 3) pCurrPixel[3] = 0xff;
						pCurrPixel += BytesPerTargetPixel;
					}
				}
			}
			else
			{
				// Raw
				const U8 ChunkPixelCount = ChunkHeader + 1;
				if (BytesPerPixel == BytesPerTargetPixel)
				{
					const UPTR ChunkSize = BytesPerPixel * ChunkPixelCount;
					if (Stream.Read(pCurrPixel, ChunkSize) != ChunkSize)
					{
						n_free(pData);
						return NULL;
					}
					pCurrPixel += ChunkSize;
				}
				else
				{
					for (UPTR Curr = 0; Curr < ChunkPixelCount; ++Curr)
					{
						U32 PixelValue;
						if (Stream.Read(&PixelValue, BytesPerPixel) != BytesPerPixel)
						{
							n_free(pData);
							return NULL;
						}
						pCurrPixel[0] = ((U8*)&PixelValue)[0];
						if (BytesPerPixel > 1) pCurrPixel[1] = ((U8*)&PixelValue)[1];
						if (BytesPerPixel > 2) pCurrPixel[2] = ((U8*)&PixelValue)[2];
						if (BytesPerTargetPixel > 3) pCurrPixel[3] = 0xff;
						pCurrPixel += BytesPerTargetPixel;
					}
				}
			}
		}
	}
	else
	{
		if (Stream.CanBeMapped()) pData = (U8*)Stream.Map();
		Mapped = !!pData;
		if (!Mapped)
		{
			UPTR DataSize = Header.ImageWidth * Header.ImageHeight * BytesPerTargetPixel;
			if (BytesPerPixel == BytesPerTargetPixel)
			{
				pData = (U8*)n_malloc(DataSize);
				if (Stream.Read(pData, DataSize) != DataSize)
				{
					n_free(pData);
					return NULL;
				}
			}
			else
			{
				U8* pCurrPixel = (U8*)pData;
				UPTR PixelCount = Header.ImageWidth * Header.ImageHeight;
				for (UPTR Curr = 0; Curr < PixelCount; ++Curr)
				{
					U32 PixelValue;
					if (Stream.Read(&PixelValue, BytesPerPixel) != BytesPerPixel)
					{
						n_free(pData);
						return NULL;
					}
					pCurrPixel[0] = ((U8*)&PixelValue)[0];
					if (BytesPerPixel > 1) pCurrPixel[1] = ((U8*)&PixelValue)[1];
					if (BytesPerPixel > 2) pCurrPixel[2] = ((U8*)&PixelValue)[2];
					if (BytesPerTargetPixel > 3) pCurrPixel[3] = 0xff;
					pCurrPixel += BytesPerTargetPixel;
				}
			}
		}
	}

	Render::PTexture Texture = GPU->CreateTexture(TexDesc, Render::Access_GPU_Read, pData, false);

	if (Mapped) Stream.Unmap();
	else n_free(pData);

	return Texture.GetUnsafe();
}
//---------------------------------------------------------------------

}<|endoftext|>