<commit_before>// Copyright (c) 2015, Matthew Malensek.
// Distributed under the BSD 2-Clause License (see LICENSE.txt for details)

#include "OSD.h"

#include "../../3RVX/Controllers/Volume/CoreAudio.h"
#include "../../3RVX/Controllers/Volume/VolumeController.h"
#include "../../3RVX/LanguageTranslator.h"
#include "../../3RVX/Logger.h"
#include "../../3RVX/Settings.h"
#include "../resource.h"

void OSD::Initialize() {
    using std::placeholders::_1;

    _osdList = new ListView(LST_OSDS, *this);
    _osdList->OnItemChange = std::bind(&OSD::OnOSDListItemChange, this, _1);

    _volumeIcon = new Checkbox(CHK_VOLICON, *this);
    _subscribeVolEvents = new Checkbox(CHK_MONITORVOL, *this);
    _subscribeVolEvents->OnClick = [this]() {
        _forceLimit->Enabled(
            _volumeGroup->Enabled() && _subscribeVolEvents->Checked());
        return true;
    };
    _audioDeviceLabel = new Label(LBL_AUDIODEV, *this);
    _audioDevice = new ComboBox(CMB_AUDIODEV, *this);
    _audioTaperLabel = new Label(LBL_AUDIOTAPER, *this);
    _audioTaper = new ComboBox(CMB_AUDIOTAPER, *this);
    _audioTaperEdit = new EditBox(ED_AUDIOTAPER, *this);
    _audioTaper->OnSelectionChange = [this]() {
        _audioTaperEdit->Enabled(_volumeGroup->Enabled()
            && _audioTaper->SelectionIndex() == _audioTaper->Count() - 1);
        return true;
    };

    _limitLabel = new Label(LBL_LIMITER, *this);
    _limitSlider = new Slider(SLD_LIMITER, *this);
    _limitValue = new Label(LBL_LIMITVAL, *this);
    _limitSlider->Buddy(_limitValue);
    _limitSlider->OnSlide = [this]() {
        std::wstring value = std::to_wstring(_limitSlider->Position()) + L"%";
        _limitValue->Text(value);
        return true;
    };
    _forceLimit = new Checkbox(CHK_FORCELIMIT, *this);
    _muteLock = new Checkbox(CHK_MUTELOCK, *this);
    _volumeGroup = new GroupBox(GRP_VOLUME, *this);
    _volumeGroup->AddChildren({
        _volumeIcon,
        _subscribeVolEvents,
        _audioDeviceLabel, _audioDevice,
        _audioTaperLabel, _audioTaper, _audioTaperEdit,
        _limitLabel, _limitSlider, _limitValue,
        _forceLimit,
        _muteLock,
    });

    _ejectIcon = new Checkbox(CHK_EJECTICON, *this);
    _subscribeEjectEvents = new Checkbox(CHK_SUBSCRIBEEJECT, *this);
    _ejectGroup = new GroupBox(GRP_EJECT, *this);
    _ejectGroup->AddChildren({
        _ejectIcon,
        _subscribeEjectEvents,
    });

    _brightnessIcon = new Checkbox(CHK_BRIGHTICON, *this);
    _brightnessGroup = new GroupBox(GRP_BRIGHTNESS, *this);
    _brightnessGroup->AddChildren({
        _brightnessIcon,
    });

    _keyboardIcon = new Checkbox(CHK_KEYICON, *this);
    _caps = new Checkbox(CHK_ENABLECAPS, *this);
    _scroll = new Checkbox(CHK_ENABLESCROLL, *this);
    _num = new Checkbox(CHK_ENABLENUM, *this);
    _media = new Checkbox(CHK_ENABLEMK, *this);
    _keyboardGroup = new GroupBox(GRP_KEYBOARD, *this);
    _keyboardGroup->AddChildren({
        _keyboardIcon,
        _caps, _scroll, _num,
        _media,
    });

    /* Define groupbox order */
    GroupBox *groups[] = {
        _volumeGroup,
        _brightnessGroup,
        _ejectGroup,
        _keyboardGroup
    };

    /* Move other groupboxes into position (same as volume) */
    int groupX = _volumeGroup->X();
    int groupY = _volumeGroup->Y();
    for (GroupBox *grp : groups) {
        grp->X(groupX);
        grp->Y(groupY);
        grp->Visible(false);
        _groups.push_back(grp);
    }
}

void OSD::LoadSettings() {
    Settings *settings = Settings::Instance();
    LanguageTranslator *translator = settings->Translator();

    /* Translations */
    _osdStr = translator->Translate(_osdStr);
    _volumeStr = translator->Translate(_volumeStr);
    _brightnessStr = translator->Translate(_brightnessStr);
    _ejectStr = translator->Translate(_ejectStr);
    _keyboardStr = translator->Translate(_keyboardStr);

    _audioDevice->AddItem(translator->Translate(L"Default"));
    _audioDevice->Select(0);
    std::wstring selectedId = settings->AudioDeviceID();
    CoreAudio *volumeCtrl = new CoreAudio(NULL);
    volumeCtrl->Init();
    _audioDevices = volumeCtrl->ListDevices();
    for (VolumeController::DeviceInfo dev : _audioDevices) {
        _audioDevice->AddItem(dev.name);
        if (dev.id == selectedId) {
            _audioDevice->Select(dev.name);
        }
    }
    volumeCtrl->Dispose();

    _taperLevels[0] = L"Disabled";
    _taperLevels[2] = L"Low";
    _taperLevels[4] = L"Medium";
    _taperLevels[6] = L"High";
    for (auto it = _taperLevels.begin(); it != _taperLevels.end(); ++it) {
        _audioTaper->AddItem(translator->Translate(it->second));
    }
    _audioTaper->AddItem(translator->Translate(L"Custom"));

    int level = settings->VolumeCurveAdjustment();
    if (_taperLevels.find(level) == _taperLevels.end()) {
        /* Select the last item (custom) */
        _audioTaper->Select(_taperLevels.size());
        _audioTaperEdit->Text(settings->VolumeCurveAdjustment());
    } else {
        _audioTaper->Select(translator->Translate(_taperLevels[level]));
    }
    _audioTaper->OnSelectionChange();

    _osdList->AddListExStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
    _osdList->AddColumn(_osdStr, (int) (_osdList->Width() * .97f));
    _osdList->AddItem(_volumeStr);
    _osdList->AddItem(_brightnessStr);
    _osdList->AddItem(_ejectStr);
    _osdList->AddItem(_keyboardStr);
    _osdList->Selection(0);

    _osdList->Checked(0, settings->VolumeOSDEnabled());
    _osdList->Checked(1, settings->BrightnessOSDEnabled());
    _osdList->Checked(2, settings->EjectOSDEnabled());
    _osdList->Checked(3, settings->KeyboardOSDEnabled());

    _volumeIcon->Checked(settings->NotifyIconEnabled());
    _subscribeVolEvents->Checked(settings->SubscribeVolumeEvents());
    _limitSlider->Position((int) (settings->VolumeLimiter() * 100.0f));
    _forceLimit->Enabled(_subscribeVolEvents->Checked());
    _muteLock->Checked(settings->MuteOnLock());

    _subscribeEjectEvents->Checked(settings->SubscribeEjectEvents());
}

void OSD::SaveSettings() {
    CLOG(L"Saving: OSD");
    Settings *settings = Settings::Instance();

    settings->VolumeOSDEnabled(_osdList->Checked(0));
    settings->BrightnessOSDEnabled(_osdList->Checked(1));
    settings->EjectOSDEnabled(_osdList->Checked(2));
    settings->KeyboardOSDEnabled(_osdList->Checked(3));

    settings->NotifyIconEnabled(_volumeIcon->Checked());
    settings->SubscribeVolumeEvents(_subscribeVolEvents->Checked());
    if (_audioTaper->SelectionIndex() == _audioTaper->Count() - 1) {
        /* Custom taper */
        settings->VolumeCurveAdjustment(_audioTaperEdit->TextAsInt());
    } else {
        /* NOTE: We multiply the taper index by two to get the actual taper
         * value. For instance, low = 2, medium = 4, etc. */
        settings->VolumeCurveAdjustment(_audioTaper->SelectionIndex() * 2);
    }
    settings->VolumeLimiter(((float) _limitSlider->Position()) / 100.0f);
    settings->MuteOnLock(_muteLock->Checked());

    settings->SubscribeEjectEvents(_subscribeEjectEvents->Checked());
}

void OSD::ShowGroup(int group) {
    for (GroupBox *grp : _groups) {
        grp->Visible(false);
    }

    GroupBox *showGroup = _groups[group];
    showGroup->Enabled(_osdList->Checked(group));
    showGroup->Visible(true);

    _audioTaper->OnSelectionChange();
    _subscribeVolEvents->OnClick();
}

void OSD::OnOSDListItemChange(NMLISTVIEW *lv) {
    if (lv->uChanged & LVIF_STATE) {
        UINT oSimg = lv->uOldState & LVIS_STATEIMAGEMASK;
        UINT nSimg = lv->uNewState & LVIS_STATEIMAGEMASK;
        if (oSimg != nSimg) {
            /* Checkbox changed */
            if (_osdList->Selection() == lv->iItem) {
                /* Activate the Apply button */
                PropSheet_Changed(GetParent(SettingsTab::DialogHandle()), NULL);

                /* NOTE: Check state at 0xF000 (1 = un, 2 = check).
                 * Shift to check:
                 * if ((nSimg >> 13) > 0) { checked } else { unchecked }
                 */

                ShowGroup(lv->iItem);
            }
        }

        if (lv->uNewState & LVIS_SELECTED) {
            ShowGroup(lv->iItem);
        }
    }
}<commit_msg>Save audio device selection<commit_after>// Copyright (c) 2015, Matthew Malensek.
// Distributed under the BSD 2-Clause License (see LICENSE.txt for details)

#include "OSD.h"

#include "../../3RVX/Controllers/Volume/CoreAudio.h"
#include "../../3RVX/Controllers/Volume/VolumeController.h"
#include "../../3RVX/LanguageTranslator.h"
#include "../../3RVX/Logger.h"
#include "../../3RVX/Settings.h"
#include "../resource.h"

void OSD::Initialize() {
    using std::placeholders::_1;

    _osdList = new ListView(LST_OSDS, *this);
    _osdList->OnItemChange = std::bind(&OSD::OnOSDListItemChange, this, _1);

    _volumeIcon = new Checkbox(CHK_VOLICON, *this);
    _subscribeVolEvents = new Checkbox(CHK_MONITORVOL, *this);
    _subscribeVolEvents->OnClick = [this]() {
        _forceLimit->Enabled(
            _volumeGroup->Enabled() && _subscribeVolEvents->Checked());
        return true;
    };
    _audioDeviceLabel = new Label(LBL_AUDIODEV, *this);
    _audioDevice = new ComboBox(CMB_AUDIODEV, *this);
    _audioTaperLabel = new Label(LBL_AUDIOTAPER, *this);
    _audioTaper = new ComboBox(CMB_AUDIOTAPER, *this);
    _audioTaperEdit = new EditBox(ED_AUDIOTAPER, *this);
    _audioTaper->OnSelectionChange = [this]() {
        _audioTaperEdit->Enabled(_volumeGroup->Enabled()
            && _audioTaper->SelectionIndex() == _audioTaper->Count() - 1);
        return true;
    };

    _limitLabel = new Label(LBL_LIMITER, *this);
    _limitSlider = new Slider(SLD_LIMITER, *this);
    _limitValue = new Label(LBL_LIMITVAL, *this);
    _limitSlider->Buddy(_limitValue);
    _limitSlider->OnSlide = [this]() {
        std::wstring value = std::to_wstring(_limitSlider->Position()) + L"%";
        _limitValue->Text(value);
        return true;
    };
    _forceLimit = new Checkbox(CHK_FORCELIMIT, *this);
    _muteLock = new Checkbox(CHK_MUTELOCK, *this);
    _volumeGroup = new GroupBox(GRP_VOLUME, *this);
    _volumeGroup->AddChildren({
        _volumeIcon,
        _subscribeVolEvents,
        _audioDeviceLabel, _audioDevice,
        _audioTaperLabel, _audioTaper, _audioTaperEdit,
        _limitLabel, _limitSlider, _limitValue,
        _forceLimit,
        _muteLock,
    });

    _ejectIcon = new Checkbox(CHK_EJECTICON, *this);
    _subscribeEjectEvents = new Checkbox(CHK_SUBSCRIBEEJECT, *this);
    _ejectGroup = new GroupBox(GRP_EJECT, *this);
    _ejectGroup->AddChildren({
        _ejectIcon,
        _subscribeEjectEvents,
    });

    _brightnessIcon = new Checkbox(CHK_BRIGHTICON, *this);
    _brightnessGroup = new GroupBox(GRP_BRIGHTNESS, *this);
    _brightnessGroup->AddChildren({
        _brightnessIcon,
    });

    _keyboardIcon = new Checkbox(CHK_KEYICON, *this);
    _caps = new Checkbox(CHK_ENABLECAPS, *this);
    _scroll = new Checkbox(CHK_ENABLESCROLL, *this);
    _num = new Checkbox(CHK_ENABLENUM, *this);
    _media = new Checkbox(CHK_ENABLEMK, *this);
    _keyboardGroup = new GroupBox(GRP_KEYBOARD, *this);
    _keyboardGroup->AddChildren({
        _keyboardIcon,
        _caps, _scroll, _num,
        _media,
    });

    /* Define groupbox order */
    GroupBox *groups[] = {
        _volumeGroup,
        _brightnessGroup,
        _ejectGroup,
        _keyboardGroup
    };

    /* Move other groupboxes into position (same as volume) */
    int groupX = _volumeGroup->X();
    int groupY = _volumeGroup->Y();
    for (GroupBox *grp : groups) {
        grp->X(groupX);
        grp->Y(groupY);
        grp->Visible(false);
        _groups.push_back(grp);
    }
}

void OSD::LoadSettings() {
    Settings *settings = Settings::Instance();
    LanguageTranslator *translator = settings->Translator();

    /* Translations */
    _osdStr = translator->Translate(_osdStr);
    _volumeStr = translator->Translate(_volumeStr);
    _brightnessStr = translator->Translate(_brightnessStr);
    _ejectStr = translator->Translate(_ejectStr);
    _keyboardStr = translator->Translate(_keyboardStr);

    _audioDevice->AddItem(translator->Translate(L"Default"));
    _audioDevice->Select(0);
    std::wstring selectedId = settings->AudioDeviceID();
    CoreAudio *volumeCtrl = new CoreAudio(NULL);
    volumeCtrl->Init();
    _audioDevices = volumeCtrl->ListDevices();
    for (VolumeController::DeviceInfo dev : _audioDevices) {
        _audioDevice->AddItem(dev.name);
        if (dev.id == selectedId) {
            _audioDevice->Select(dev.name);
        }
    }
    volumeCtrl->Dispose();

    _taperLevels[0] = L"Disabled";
    _taperLevels[2] = L"Low";
    _taperLevels[4] = L"Medium";
    _taperLevels[6] = L"High";
    for (auto it = _taperLevels.begin(); it != _taperLevels.end(); ++it) {
        _audioTaper->AddItem(translator->Translate(it->second));
    }
    _audioTaper->AddItem(translator->Translate(L"Custom"));

    int level = settings->VolumeCurveAdjustment();
    if (_taperLevels.find(level) == _taperLevels.end()) {
        /* Select the last item (custom) */
        _audioTaper->Select(_taperLevels.size());
        _audioTaperEdit->Text(settings->VolumeCurveAdjustment());
    } else {
        _audioTaper->Select(translator->Translate(_taperLevels[level]));
    }
    _audioTaper->OnSelectionChange();

    _osdList->AddListExStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
    _osdList->AddColumn(_osdStr, (int) (_osdList->Width() * .97f));
    _osdList->AddItem(_volumeStr);
    _osdList->AddItem(_brightnessStr);
    _osdList->AddItem(_ejectStr);
    _osdList->AddItem(_keyboardStr);
    _osdList->Selection(0);

    _osdList->Checked(0, settings->VolumeOSDEnabled());
    _osdList->Checked(1, settings->BrightnessOSDEnabled());
    _osdList->Checked(2, settings->EjectOSDEnabled());
    _osdList->Checked(3, settings->KeyboardOSDEnabled());

    _volumeIcon->Checked(settings->NotifyIconEnabled());
    _subscribeVolEvents->Checked(settings->SubscribeVolumeEvents());
    _limitSlider->Position((int) (settings->VolumeLimiter() * 100.0f));
    _forceLimit->Enabled(_subscribeVolEvents->Checked());
    _muteLock->Checked(settings->MuteOnLock());

    _subscribeEjectEvents->Checked(settings->SubscribeEjectEvents());
}

void OSD::SaveSettings() {
    CLOG(L"Saving: OSD");
    Settings *settings = Settings::Instance();

    settings->VolumeOSDEnabled(_osdList->Checked(0));
    settings->BrightnessOSDEnabled(_osdList->Checked(1));
    settings->EjectOSDEnabled(_osdList->Checked(2));
    settings->KeyboardOSDEnabled(_osdList->Checked(3));

    settings->NotifyIconEnabled(_volumeIcon->Checked());
    settings->SubscribeVolumeEvents(_subscribeVolEvents->Checked());
    int selectedDevice = _audioDevice->SelectionIndex();
    if (selectedDevice == 0) {
        settings->AudioDeviceID(L"");
    } else {
        settings->AudioDeviceID(_audioDevices[selectedDevice - 1].id);
    }
    if (_audioTaper->SelectionIndex() == _audioTaper->Count() - 1) {
        /* Custom taper */
        settings->VolumeCurveAdjustment(_audioTaperEdit->TextAsInt());
    } else {
        /* NOTE: We multiply the taper index by two to get the actual taper
         * value. For instance, low = 2, medium = 4, etc. */
        settings->VolumeCurveAdjustment(_audioTaper->SelectionIndex() * 2);
    }
    settings->VolumeLimiter(((float) _limitSlider->Position()) / 100.0f);
    settings->MuteOnLock(_muteLock->Checked());

    settings->SubscribeEjectEvents(_subscribeEjectEvents->Checked());
}

void OSD::ShowGroup(int group) {
    for (GroupBox *grp : _groups) {
        grp->Visible(false);
    }

    GroupBox *showGroup = _groups[group];
    showGroup->Enabled(_osdList->Checked(group));
    showGroup->Visible(true);

    _audioTaper->OnSelectionChange();
    _subscribeVolEvents->OnClick();
}

void OSD::OnOSDListItemChange(NMLISTVIEW *lv) {
    if (lv->uChanged & LVIF_STATE) {
        UINT oSimg = lv->uOldState & LVIS_STATEIMAGEMASK;
        UINT nSimg = lv->uNewState & LVIS_STATEIMAGEMASK;
        if (oSimg != nSimg) {
            /* Checkbox changed */
            if (_osdList->Selection() == lv->iItem) {
                /* Activate the Apply button */
                PropSheet_Changed(GetParent(SettingsTab::DialogHandle()), NULL);

                /* NOTE: Check state at 0xF000 (1 = un, 2 = check).
                 * Shift to check:
                 * if ((nSimg >> 13) > 0) { checked } else { unchecked }
                 */

                ShowGroup(lv->iItem);
            }
        }

        if (lv->uNewState & LVIS_SELECTED) {
            ShowGroup(lv->iItem);
        }
    }
}<|endoftext|>


<commit_before>#include "SysConfig.h"
#if(HAS_STD_LIGHTS)

// Includes
#include <Arduino.h>
#include "CLights.h"
#include "NCommManager.h"

namespace
{
	// 1% per 10ms
	const float kPowerDelta = 0.01f;

	bool isGreeting 		= false;
	bool greetState 		= false;
	int greetCycle 			= 0;
	const int cycleCount 	= 6;
    const int greetDelay_ms = 600;

	inline uint32_t PercentToAnalog( float x )
	{
		if( x < 0.0f )
		{
			return 0;
		}
		else if( x < 0.33f )
		{
			// Linear region, 0-80
			return static_cast<uint32_t>( 242.424f * x );
		}
		else
		{
			// Parabolic region 80-255
			return static_cast<uint32_t>( ( 308.571f * x * x ) - ( 147.426f * x ) + 95.0f );
		}
	}
}

CLights::CLights( uint32_t pinIn )
	: m_pin( pinIn, CPin::kAnalog, CPin::kOutput )
{
}

void CLights::Initialize()
{
	// Reset pin
	m_pin.Reset();
	m_pin.Write( 0 );

	// Reset timers
    m_controlTimer.Reset();
    m_telemetryTimer.Reset();
}

void CLights::Update( CCommand& commandIn )
{
	// Check for messages
	if( !NCommManager::m_isCommandAvailable )
	{
		return;
	}

	// Handle messages
	if( commandIn.Equals( "lights_tpow" ) )
	{
		// Update the target position
		m_targetPower = orutil::Decode1K( commandIn.m_arguments[1] );

		// TODO: Ideally this unit would have the ability to autonomously set its own target and ack receipt with a separate mechanism
		// Acknowledge target position
		Serial.print( F( "lights_tpow:" ) );
		Serial.print( commandIn.m_arguments[1] );
		Serial.println( ';' );

		// Pass through linearization function
		m_targetPower_an = PercentToAnalog( m_targetPower );

		// Apply ceiling
		if( m_targetPower_an > 255 )
		{
			m_targetPower_an = 255;
		}

		// Directly move to target power
		m_currentPower 		= m_targetPower;
		m_currentPower_an 	= m_targetPower_an;

		// Write the power value to the pin
		m_pin.Write( m_currentPower_an );

		// Emit current power
		Serial.print( F( "lights_pow:" ) );
		Serial.print( orutil::Encode1K( m_currentPower ) );
		Serial.print( ';' );
	}
	else if( command.Equals( "wake" ) )
    {
        // Set greeting state to true and reset timer
        isGreeting = true;
        m_controlTimer.Reset();

		// Set light state to off
		greetState = false;
		m_pin.Write( 0 );
    }

    if( isGreeting )
    {
        if( controltime.HasElapsed( greetDelay_ms ) )
        {
           // Set to opposite state
		   if( greetState )
		   {
			   greetState = false;
			   m_pin.Write( 0 );
		   }
		   else
		   {
			   greetState = true;
			   m_pin.Write( 1 );
		   }

		   greetCycle++;

		   if( greetCycle >= cycleCount )
		   {
			   // Done blinking
			   isGreeting = false;

			   // Reset pin back to its original value
			   m_pin.Write( m_currentPower_an );
		   }
        }
    }
}

#endif
<commit_msg>Fixed typo in command name<commit_after>#include "SysConfig.h"
#if(HAS_STD_LIGHTS)

// Includes
#include <Arduino.h>
#include "CLights.h"
#include "NCommManager.h"

namespace
{
	// 1% per 10ms
	const float kPowerDelta = 0.01f;

	bool isGreeting 		= false;
	bool greetState 		= false;
	int greetCycle 			= 0;
	const int cycleCount 	= 6;
    const int greetDelay_ms = 600;

	inline uint32_t PercentToAnalog( float x )
	{
		if( x < 0.0f )
		{
			return 0;
		}
		else if( x < 0.33f )
		{
			// Linear region, 0-80
			return static_cast<uint32_t>( 242.424f * x );
		}
		else
		{
			// Parabolic region 80-255
			return static_cast<uint32_t>( ( 308.571f * x * x ) - ( 147.426f * x ) + 95.0f );
		}
	}
}

CLights::CLights( uint32_t pinIn )
	: m_pin( pinIn, CPin::kAnalog, CPin::kOutput )
{
}

void CLights::Initialize()
{
	// Reset pin
	m_pin.Reset();
	m_pin.Write( 0 );

	// Reset timers
    m_controlTimer.Reset();
    m_telemetryTimer.Reset();
}

void CLights::Update( CCommand& commandIn )
{
	// Check for messages
	if( !NCommManager::m_isCommandAvailable )
	{
		return;
	}

	// Handle messages
	if( commandIn.Equals( "lights_tpow" ) )
	{
		// Update the target position
		m_targetPower = orutil::Decode1K( commandIn.m_arguments[1] );

		// TODO: Ideally this unit would have the ability to autonomously set its own target and ack receipt with a separate mechanism
		// Acknowledge target position
		Serial.print( F( "lights_tpow:" ) );
		Serial.print( commandIn.m_arguments[1] );
		Serial.println( ';' );

		// Pass through linearization function
		m_targetPower_an = PercentToAnalog( m_targetPower );

		// Apply ceiling
		if( m_targetPower_an > 255 )
		{
			m_targetPower_an = 255;
		}

		// Directly move to target power
		m_currentPower 		= m_targetPower;
		m_currentPower_an 	= m_targetPower_an;

		// Write the power value to the pin
		m_pin.Write( m_currentPower_an );

		// Emit current power
		Serial.print( F( "lights_pow:" ) );
		Serial.print( orutil::Encode1K( m_currentPower ) );
		Serial.print( ';' );
	}
	else if( commandIn.Equals( "wake" ) )
    {
        // Set greeting state to true and reset timer
        isGreeting = true;
        m_controlTimer.Reset();

		// Set light state to off
		greetState = false;
		m_pin.Write( 0 );
    }

    if( isGreeting )
    {
        if( controltime.HasElapsed( greetDelay_ms ) )
        {
           // Set to opposite state
		   if( greetState )
		   {
			   greetState = false;
			   m_pin.Write( 0 );
		   }
		   else
		   {
			   greetState = true;
			   m_pin.Write( 1 );
		   }

		   greetCycle++;

		   if( greetCycle >= cycleCount )
		   {
			   // Done blinking
			   isGreeting = false;

			   // Reset pin back to its original value
			   m_pin.Write( m_currentPower_an );
		   }
        }
    }
}

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: tools.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2004-11-26 19:22:22 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SLIDESHOW_TOOLS_HXX
#define _SLIDESHOW_TOOLS_HXX

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif
#ifndef _BGFX_RANGE_B2DRECTANGLE_HXX
#include <basegfx/range/b2drectangle.hxx>
#endif
#ifndef _BGFX_TUPLE_B2DTUPLE_HXX
#include <basegfx/tuple/b2dtuple.hxx>
#endif
#ifndef _BGFX_VECTOR_B2DSIZE_HXX
#include <basegfx/vector/b2dsize.hxx>
#endif

#ifndef BOOST_BIND_HPP_INCLUDED
#include <boost/bind.hpp>
#endif
#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
#include <boost/shared_ptr.hpp>
#endif

#include <shapeattributelayer.hxx>

#include <string.h> // for strcmp
#include <algorithm>

#include <shape.hxx>
#include <rgbcolor.hxx>
#include <hslcolor.hxx>
#include <layermanager.hxx>

namespace com { namespace sun { namespace star { namespace beans
{
    struct NamedValue;
} } } }

/* Definition of some animation tools */

namespace presentation
{
    namespace internal
    {
        // Value extraction from Any
        // =========================

        /// extract unary double value from Any
        bool extractValue( double&                              o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract enum/constant group value from Any
        bool extractValue( sal_Int16&                           o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract color value from Any
        bool extractValue( RGBColor&                            o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract color value from Any
        bool extractValue( HSLColor&                            o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract plain string from Any
        bool extractValue( ::rtl::OUString&                     o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract bool value from Any
        bool extractValue( bool&                                o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract double 2-tuple from Any
        bool extractValue( ::basegfx::B2DTuple&                 o_rPair,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /** Search a sequence of NamedValues for a given element.

            @return true, if the sequence contains the specified
            element.
         */
        bool findNamedValue( ::com::sun::star::uno::Sequence<
                                 ::com::sun::star::beans::NamedValue >&     rSequence,
                             const ::com::sun::star::beans::NamedValue& rSearchKey );

        /** Search a sequence of NamedValues for an element with a given name.

            @param o_pRet
            If non-NULL, receives the full NamedValue found (if it was
            found, that is).

            @return true, if the sequence contains the specified
            element.
         */
        bool findNamedValue( ::com::sun::star::beans::NamedValue*       o_pRet,
                             const ::com::sun::star::uno::Sequence<
                                 ::com::sun::star::beans::NamedValue >&     rSequence,
                             const ::rtl::OUString&                     rSearchString );

        template< typename ValueType > class ValueMap
        {
        public:
            struct MapEntry
            {
                const char*     maKey;
                ValueType       maValue;
            };

            ValueMap( const MapEntry*   pMap,
                      ::std::size_t     nEntries,
                      bool              bCaseSensitive ) :
                mpMap( pMap ),
                mnEntries( nEntries ),
                mbCaseSensitive( bCaseSensitive )
            {
#ifdef DBG_UTIL
                // Ensure that map entries are sorted (and all lowercase, if this
                // map is case insensitive)
                const ::rtl::OString aStr( pMap->maKey );
                if( !mbCaseSensitive &&
                    aStr != aStr.toAsciiLowerCase() )
                {
                    OSL_TRACE("ValueMap::ValueMap(): Key %s is not lowercase",
                              pMap->maKey);
                    OSL_ENSURE( false, "ValueMap::ValueMap(): Key is not lowercase" );
                }

                if( mnEntries > 1 )
                {
                    for( ::std::size_t i=0; i<mnEntries-1; ++i, ++pMap )
                    {
                        if( !mapComparator(pMap[0], pMap[1]) &&
                            mapComparator(pMap[1], pMap[0]) )
                        {
                            OSL_TRACE("ValueMap::ValueMap(): Map is not sorted, keys %s and %s are wrong",
                                       pMap[0].maKey,
                                       pMap[1].maKey);
                            OSL_ENSURE( false,
                                        "ValueMap::ValueMap(): Map is not sorted" );
                        }

                        const ::rtl::OString aStr( pMap[1].maKey );
                        if( !mbCaseSensitive &&
                            aStr != aStr.toAsciiLowerCase() )
                        {
                            OSL_TRACE("ValueMap::ValueMap(): Key %s is not lowercase",
                                      pMap[1].maKey);
                            OSL_ENSURE( false, "ValueMap::ValueMap(): Key is not lowercase" );
                        }
                    }
                }
#endif
            }

            bool lookup( const ::rtl::OUString& rName,
                         ValueType&             o_rResult ) const
            {
                // rName is required to contain only ASCII characters.
                // TODO(Q1): Enforce this at upper layers
                ::rtl::OString aKey( ::rtl::OUStringToOString( mbCaseSensitive ? rName : rName.toAsciiLowerCase(),
                                                               RTL_TEXTENCODING_ASCII_US ) );
                MapEntry aSearchKey =
                    {
                        aKey.getStr(),
                        ValueType()
                    };

                const MapEntry* pRes;
                const MapEntry* pEnd = mpMap+mnEntries;
                if( (pRes=::std::lower_bound( mpMap,
                                              pEnd,
                                              aSearchKey,
                                              &mapComparator )) != pEnd )
                {
                    // place to _insert before_ found - is it equal to
                    // the search key?
                    if( strcmp( pRes->maKey, aSearchKey.maKey ) == 0 )
                    {
                        // yep, correct entry found
                        o_rResult = pRes->maValue;
                        return true;
                    }
                }

                // not found
                return false;
            }

        private:
            static bool mapComparator( const MapEntry& rLHS,
                                       const MapEntry& rRHS )
            {
                return strcmp( rLHS.maKey,
                               rRHS.maKey ) < 0;
            }

            const MapEntry*     mpMap;
            ::std::size_t       mnEntries;
            bool                mbCaseSensitive;
        };

        inline ::basegfx::B2DRectangle calcRelativeShapeBounds( const ::basegfx::B2DRectangle& rPageBounds,
                                                                const ::basegfx::B2DRectangle& rShapeBounds )
        {
            return ::basegfx::B2DRectangle( rShapeBounds.getMinX() / rPageBounds.getWidth(),
                                            rShapeBounds.getMinY() / rPageBounds.getHeight(),
                                            rShapeBounds.getMaxX() / rPageBounds.getWidth(),
                                            rShapeBounds.getMaxY() / rPageBounds.getHeight() );
        }

        /** Get the shape transformation from the attribute set

            @param rBounds
            Shape bound rect

            @param pAttr
            Attribute set. Might be NULL

            @param bWithTranslation
            Whether the transformation should contain translation
            to shape output position, or not (e.g. for sprites)
        */
        ::basegfx::B2DHomMatrix getShapeTransformation( const ::basegfx::B2DRectangle&      rOrigBounds,
                                                        const ::basegfx::B2DRectangle&      rBounds,
                                                        const ShapeAttributeLayerSharedPtr& pAttr,
                                                        bool                                bWithTranslation );

        /** Calc update area for a shape.

            This method calculates the 'covered' area for the shape,
            i.e. the rectangle that is affected when rendering the
            shape.

            @param rShapeBounds
            Bound rect of the shape (without any transformations taken
            into account).

            @param rShapeTransform
            Transformation matrix the shape should undergo.

            @param pAttr
            Current shape attributes
         */
        ::basegfx::B2DRectangle getShapeUpdateArea( const ::basegfx::B2DRectangle&      rShapeBounds,
                                                    const ::basegfx::B2DHomMatrix&      rShapeTransform,
                                                    const ShapeAttributeLayerSharedPtr& pAttr );

        /** Convert a plain UNO API 32 bit int to RGBColor
         */
        RGBColor unoColor2RGBColor( sal_Int32 );

    }
}

#endif /* _SLIDESHOW_TOOLS_HXX */
<commit_msg>INTEGRATION: CWS presfixes01 (1.2.6); FILE MERGED 2005/02/02 22:47:01 dbo 1.2.6.2: #i37777# - timing changes for activities queue - minor fixes Issue number: Submitted by: Reviewed by: 2005/01/26 11:20:06 dbo 1.2.6.1: #i39787# more helpers Issue number: Submitted by: Reviewed by:<commit_after>/*************************************************************************
 *
 *  $RCSfile: tools.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-10 13:56:56 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SLIDESHOW_TOOLS_HXX
#define _SLIDESHOW_TOOLS_HXX

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif
#ifndef _BGFX_RANGE_B2DRECTANGLE_HXX
#include <basegfx/range/b2drectangle.hxx>
#endif
#ifndef _BGFX_TUPLE_B2DTUPLE_HXX
#include <basegfx/tuple/b2dtuple.hxx>
#endif
#ifndef _BGFX_VECTOR_B2DSIZE_HXX
#include <basegfx/vector/b2dsize.hxx>
#endif

#ifndef BOOST_BIND_HPP_INCLUDED
#include <boost/bind.hpp>
#endif
#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
#include <boost/shared_ptr.hpp>
#endif

#include <shapeattributelayer.hxx>

#include <string.h> // for strcmp
#include <algorithm>

#include <shape.hxx>
#include <rgbcolor.hxx>
#include <hslcolor.hxx>
#include <layermanager.hxx>

#include "boost/optional.hpp"
#include <cstdlib>

namespace com { namespace sun { namespace star { namespace beans
{
    struct NamedValue;
} } } }

/* Definition of some animation tools */

namespace presentation
{
    namespace internal
    {
        // Value extraction from Any
        // =========================

        /// extract unary double value from Any
        bool extractValue( double&                              o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract enum/constant group value from Any
        bool extractValue( sal_Int16&                           o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract color value from Any
        bool extractValue( RGBColor&                            o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract color value from Any
        bool extractValue( HSLColor&                            o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract plain string from Any
        bool extractValue( ::rtl::OUString&                     o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract bool value from Any
        bool extractValue( bool&                                o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract double 2-tuple from Any
        bool extractValue( ::basegfx::B2DTuple&                 o_rPair,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /** Search a sequence of NamedValues for a given element.

            @return true, if the sequence contains the specified
            element.
         */
        bool findNamedValue( ::com::sun::star::uno::Sequence<
                                 ::com::sun::star::beans::NamedValue >&     rSequence,
                             const ::com::sun::star::beans::NamedValue& rSearchKey );

        /** Search a sequence of NamedValues for an element with a given name.

            @param o_pRet
            If non-NULL, receives the full NamedValue found (if it was
            found, that is).

            @return true, if the sequence contains the specified
            element.
         */
        bool findNamedValue( ::com::sun::star::beans::NamedValue*       o_pRet,
                             const ::com::sun::star::uno::Sequence<
                                 ::com::sun::star::beans::NamedValue >&     rSequence,
                             const ::rtl::OUString&                     rSearchString );

        template< typename ValueType > class ValueMap
        {
        public:
            struct MapEntry
            {
                const char*     maKey;
                ValueType       maValue;
            };

            ValueMap( const MapEntry*   pMap,
                      ::std::size_t     nEntries,
                      bool              bCaseSensitive ) :
                mpMap( pMap ),
                mnEntries( nEntries ),
                mbCaseSensitive( bCaseSensitive )
            {
#ifdef DBG_UTIL
                // Ensure that map entries are sorted (and all lowercase, if this
                // map is case insensitive)
                const ::rtl::OString aStr( pMap->maKey );
                if( !mbCaseSensitive &&
                    aStr != aStr.toAsciiLowerCase() )
                {
                    OSL_TRACE("ValueMap::ValueMap(): Key %s is not lowercase",
                              pMap->maKey);
                    OSL_ENSURE( false, "ValueMap::ValueMap(): Key is not lowercase" );
                }

                if( mnEntries > 1 )
                {
                    for( ::std::size_t i=0; i<mnEntries-1; ++i, ++pMap )
                    {
                        if( !mapComparator(pMap[0], pMap[1]) &&
                            mapComparator(pMap[1], pMap[0]) )
                        {
                            OSL_TRACE("ValueMap::ValueMap(): Map is not sorted, keys %s and %s are wrong",
                                       pMap[0].maKey,
                                       pMap[1].maKey);
                            OSL_ENSURE( false,
                                        "ValueMap::ValueMap(): Map is not sorted" );
                        }

                        const ::rtl::OString aStr( pMap[1].maKey );
                        if( !mbCaseSensitive &&
                            aStr != aStr.toAsciiLowerCase() )
                        {
                            OSL_TRACE("ValueMap::ValueMap(): Key %s is not lowercase",
                                      pMap[1].maKey);
                            OSL_ENSURE( false, "ValueMap::ValueMap(): Key is not lowercase" );
                        }
                    }
                }
#endif
            }

            bool lookup( const ::rtl::OUString& rName,
                         ValueType&             o_rResult ) const
            {
                // rName is required to contain only ASCII characters.
                // TODO(Q1): Enforce this at upper layers
                ::rtl::OString aKey( ::rtl::OUStringToOString( mbCaseSensitive ? rName : rName.toAsciiLowerCase(),
                                                               RTL_TEXTENCODING_ASCII_US ) );
                MapEntry aSearchKey =
                    {
                        aKey.getStr(),
                        ValueType()
                    };

                const MapEntry* pRes;
                const MapEntry* pEnd = mpMap+mnEntries;
                if( (pRes=::std::lower_bound( mpMap,
                                              pEnd,
                                              aSearchKey,
                                              &mapComparator )) != pEnd )
                {
                    // place to _insert before_ found - is it equal to
                    // the search key?
                    if( strcmp( pRes->maKey, aSearchKey.maKey ) == 0 )
                    {
                        // yep, correct entry found
                        o_rResult = pRes->maValue;
                        return true;
                    }
                }

                // not found
                return false;
            }

        private:
            static bool mapComparator( const MapEntry& rLHS,
                                       const MapEntry& rRHS )
            {
                return strcmp( rLHS.maKey,
                               rRHS.maKey ) < 0;
            }

            const MapEntry*     mpMap;
            ::std::size_t       mnEntries;
            bool                mbCaseSensitive;
        };

        inline ::basegfx::B2DRectangle calcRelativeShapeBounds( const ::basegfx::B2DRectangle& rPageBounds,
                                                                const ::basegfx::B2DRectangle& rShapeBounds )
        {
            return ::basegfx::B2DRectangle( rShapeBounds.getMinX() / rPageBounds.getWidth(),
                                            rShapeBounds.getMinY() / rPageBounds.getHeight(),
                                            rShapeBounds.getMaxX() / rPageBounds.getWidth(),
                                            rShapeBounds.getMaxY() / rPageBounds.getHeight() );
        }

        /** Get the shape transformation from the attribute set

            @param rBounds
            Shape bound rect

            @param pAttr
            Attribute set. Might be NULL

            @param bWithTranslation
            Whether the transformation should contain translation
            to shape output position, or not (e.g. for sprites)
        */
        ::basegfx::B2DHomMatrix getShapeTransformation( const ::basegfx::B2DRectangle&      rOrigBounds,
                                                        const ::basegfx::B2DRectangle&      rBounds,
                                                        const ShapeAttributeLayerSharedPtr& pAttr,
                                                        bool                                bWithTranslation );

        /** Calc update area for a shape.

            This method calculates the 'covered' area for the shape,
            i.e. the rectangle that is affected when rendering the
            shape.

            @param rShapeBounds
            Bound rect of the shape (without any transformations taken
            into account).

            @param rShapeTransform
            Transformation matrix the shape should undergo.

            @param pAttr
            Current shape attributes
         */
        ::basegfx::B2DRectangle getShapeUpdateArea( const ::basegfx::B2DRectangle&      rShapeBounds,
                                                    const ::basegfx::B2DHomMatrix&      rShapeTransform,
                                                    const ShapeAttributeLayerSharedPtr& pAttr );

        /** Convert a plain UNO API 32 bit int to RGBColor
         */
        RGBColor unoColor2RGBColor( sal_Int32 );

        /// Gets a random ordinal [0,n)
        inline ::std::size_t getRandomOrdinal( const ::std::size_t n )
        {
            return static_cast< ::std::size_t >(
                double(n) * rand() / (RAND_MAX + 1.0) );
        }

        /// To work around ternary operator in initializer lists
        /// (Solaris compiler problems)
        template <typename T>
        inline T const & ternary_op(
            const bool cond, T const & arg1, T const & arg2 )
        {
            if (cond)
                return arg1;
            else
                return arg2;
        }
    }
}

#endif /* _SLIDESHOW_TOOLS_HXX */
<|endoftext|>


<commit_before>struct Scope;
struct Checker;
struct Type;
struct DeclInfo;
struct lbModule;
struct lbProcedure;

#define ENTITY_KINDS \
	ENTITY_KIND(Invalid) \
	ENTITY_KIND(Constant) \
	ENTITY_KIND(Variable) \
	ENTITY_KIND(TypeName) \
	ENTITY_KIND(Procedure) \
	ENTITY_KIND(ProcGroup) \
	ENTITY_KIND(Builtin) \
	ENTITY_KIND(ImportName) \
	ENTITY_KIND(LibraryName) \
	ENTITY_KIND(Nil) \
	ENTITY_KIND(Label)

enum EntityKind {
#define ENTITY_KIND(k) GB_JOIN2(Entity_, k),
	ENTITY_KINDS
#undef ENTITY_KIND
	Entity_Count,
};

String const entity_strings[] = {
#define ENTITY_KIND(k) {cast(u8 *)#k, gb_size_of(#k)-1},
	ENTITY_KINDS
#undef ENTITY_KIND
};

enum EntityFlag : u64 {
	EntityFlag_Visited       = 1ull<<0,
	EntityFlag_Used          = 1ull<<1,
	EntityFlag_Using         = 1ull<<2,
	EntityFlag_Field         = 1ull<<3,
	EntityFlag_Param         = 1ull<<4,
	EntityFlag_Result        = 1ull<<5,
	EntityFlag_ArrayElem     = 1ull<<6,
	EntityFlag_ArraySwizzle  = 1ull<<7,
	EntityFlag_Ellipsis      = 1ull<<8,
	EntityFlag_NoAlias       = 1ull<<9,
	EntityFlag_TypeField     = 1ull<<10,
	EntityFlag_Value         = 1ull<<11,
	EntityFlag_Sret          = 1ull<<12,
	EntityFlag_ByVal         = 1ull<<13,
	EntityFlag_BitFieldValue = 1ull<<14,
	EntityFlag_PolyConst     = 1ull<<15,
	EntityFlag_NotExported   = 1ull<<16,
	EntityFlag_ConstInput    = 1ull<<17,

	EntityFlag_Static        = 1ull<<18,

	EntityFlag_ImplicitReference = 1ull<<19, // NOTE(bill): equivalent to `const &` in C++

	EntityFlag_SoaPtrField   = 1ull<<20, // to allow s.x[0] where `s.x` is a pointer rather than a slice

	EntityFlag_ProcBodyChecked = 1ull<<21,

	EntityFlag_CVarArg       = 1ull<<22,
	EntityFlag_AutoCast      = 1ull<<23,
	EntityFlag_AnyInt        = 1ull<<24,

	EntityFlag_Disabled      = 1ull<<25,
	EntityFlag_Cold          = 1ull<<26, // procedure is rarely called

	EntityFlag_Lazy          = 1ull<<27, // Lazily type checked

	EntityFlag_Test          = 1ull<<30,

	EntityFlag_Overridden    = 1ull<<63,

};

enum EntityState : u32 {
	EntityState_Unresolved = 0,
	EntityState_InProgress = 1,
	EntityState_Resolved   = 2,
};

enum ParameterValueKind {
	ParameterValue_Invalid,
	ParameterValue_Constant,
	ParameterValue_Nil,
	ParameterValue_Location,
	ParameterValue_Value,
};

struct ParameterValue {
	ParameterValueKind kind;
	Ast *original_ast_expr;
	union {
		ExactValue value;
		Ast *ast_value;
	};
};

enum EntityConstantFlags : u32 {
	EntityConstantFlag_ImplicitEnumValue = 1<<0,
};

enum ProcedureOptimizationMode : u32 {
	ProcedureOptimizationMode_Default,
	ProcedureOptimizationMode_None,
	ProcedureOptimizationMode_Minimal,
	ProcedureOptimizationMode_Size,
	ProcedureOptimizationMode_Speed,
};

// An Entity is a named "thing" in the language
struct Entity {
	EntityKind  kind;
	u64         id;
	std::atomic<u64>         flags;
	std::atomic<EntityState> state;
	Token       token;
	Scope *     scope;
	Type *      type;
	std::atomic<Ast *> identifier; // Can be nullptr
	DeclInfo *  decl_info;
	DeclInfo *  parent_proc_decl; // nullptr if in file/global scope
	AstFile *   file;
	AstPackage *pkg;

	// TODO(bill): Cleanup how `using` works for entities
	Entity *    using_parent;
	Ast *       using_expr;

	Entity *    aliased_of;

	lbModule *   code_gen_module;
	lbProcedure *code_gen_procedure;

	u64         order_in_src;
	String      deprecated_message;
	String      warning_message;

	// IMPORTANT NOTE(bill): This must be a discriminated union because of patching
	// later entity kinds
	union {
		struct {
			u8 start;
		} Dummy;
		struct {
			ExactValue value;
			ParameterValue param_value;
			u32 flags;
		} Constant;
		struct {
			Ast *init_expr; // only used for some variables within procedure bodies
			i32        field_index;
			i32        field_src_index;

			ParameterValue param_value;
			Ast *          param_expr;

			String     thread_local_model;
			Entity *   foreign_library;
			Ast *      foreign_library_ident;
			String     link_name;
			String     link_prefix;
			String     link_section;
			bool       is_foreign;
			bool       is_export;
		} Variable;
		struct {
			Type * type_parameter_specialization;
			String ir_mangled_name;
			bool   is_type_alias;
		} TypeName;
		struct {
			u64     tags;
			Entity *foreign_library;
			Ast *   foreign_library_ident;
			String  link_name;
			String  link_prefix;
			DeferredProcedure deferred_procedure;
			bool    is_foreign;
			bool    is_export;
			ProcedureOptimizationMode optimization_mode;
		} Procedure;
		struct {
			Array<Entity *> entities;
		} ProcGroup;
		struct {
			i32 id;
		} Builtin;
		struct {
			String path;
			String name;
			Scope *scope;
		} ImportName;
		struct {
			Slice<String> paths;
			String name;
		} LibraryName;
		i32 Nil;
		struct {
			String name;
			Ast *node;
			Ast *parent;
		} Label;
	};
};

bool is_entity_kind_exported(EntityKind kind, bool allow_builtin = false) {
	switch (kind) {
	case Entity_Builtin:
		return allow_builtin;
	case Entity_ImportName:
	case Entity_LibraryName:
	case Entity_Nil:
		return false;
	}
	return true;
}

bool is_entity_exported(Entity *e, bool allow_builtin = false) {
	// TODO(bill): Determine the actual exportation rules for imports of entities
	GB_ASSERT(e != nullptr);
	if (!is_entity_kind_exported(e->kind, allow_builtin)) {
		return false;
	}

	if (e->flags & EntityFlag_NotExported) {
		return false;
	}
	if (e->file != nullptr && (e->file->flags & AstFile_IsPrivate) != 0) {
		return false;
	}

	String name = e->token.string;
	switch (name.len) {
	case 0: return false;
	case 1: return name[0] != '_';
	}
	return true;
}

bool entity_has_deferred_procedure(Entity *e) {
	GB_ASSERT(e != nullptr);
	if (e->kind == Entity_Procedure) {
		return e->Procedure.deferred_procedure.entity != nullptr;
	}
	return false;
}

gb_global u64 global_entity_id = 0;

Entity *alloc_entity(EntityKind kind, Scope *scope, Token token, Type *type) {
	gbAllocator a = permanent_allocator();
	Entity *entity = gb_alloc_item(a, Entity);
	entity->kind   = kind;
	entity->state  = EntityState_Unresolved;
	entity->scope  = scope;
	entity->token  = token;
	entity->type   = type;
	entity->id     = ++global_entity_id;
	return entity;
}

Entity *alloc_entity_variable(Scope *scope, Token token, Type *type, EntityState state = EntityState_Unresolved) {
	Entity *entity = alloc_entity(Entity_Variable, scope, token, type);
	entity->state = state;
	return entity;
}

Entity *alloc_entity_using_variable(Entity *parent, Token token, Type *type, Ast *using_expr) {
	GB_ASSERT(parent != nullptr);
	token.pos = parent->token.pos;
	Entity *entity = alloc_entity(Entity_Variable, parent->scope, token, type);
	entity->using_parent = parent;
	entity->parent_proc_decl = parent->parent_proc_decl;
	entity->using_expr = using_expr;
	entity->flags |= EntityFlag_Using;
	entity->flags |= EntityFlag_Used;
	entity->state = EntityState_Resolved;
	return entity;
}

Entity *alloc_entity_constant(Scope *scope, Token token, Type *type, ExactValue value) {
	Entity *entity = alloc_entity(Entity_Constant, scope, token, type);
	entity->Constant.value = value;
	return entity;
}

Entity *alloc_entity_type_name(Scope *scope, Token token, Type *type, EntityState state = EntityState_Unresolved) {
	Entity *entity = alloc_entity(Entity_TypeName, scope, token, type);
	entity->state = state;
	return entity;
}

Entity *alloc_entity_param(Scope *scope, Token token, Type *type, bool is_using, bool is_value) {
	Entity *entity = alloc_entity_variable(scope, token, type);
	entity->flags |= EntityFlag_Used;
	entity->flags |= EntityFlag_Param;
	entity->state = EntityState_Resolved;
	if (is_using) entity->flags |= EntityFlag_Using;
	if (is_value) entity->flags |= EntityFlag_Value;
	return entity;
}

Entity *alloc_entity_const_param(Scope *scope, Token token, Type *type, ExactValue value, bool poly_const) {
	Entity *entity = alloc_entity_constant(scope, token, type, value);
	entity->flags |= EntityFlag_Used;
	if (poly_const) entity->flags |= EntityFlag_PolyConst;
	entity->flags |= EntityFlag_Param;
	return entity;
}

Entity *alloc_entity_field(Scope *scope, Token token, Type *type, bool is_using, i32 field_src_index, EntityState state = EntityState_Unresolved) {
	Entity *entity = alloc_entity_variable(scope, token, type);
	entity->Variable.field_src_index = field_src_index;
	entity->Variable.field_index = field_src_index;
	if (is_using) entity->flags |= EntityFlag_Using;
	entity->flags |= EntityFlag_Field;
	entity->state = state;
	return entity;
}

Entity *alloc_entity_array_elem(Scope *scope, Token token, Type *type, i32 field_src_index) {
	Entity *entity = alloc_entity_variable(scope, token, type);
	entity->Variable.field_src_index = field_src_index;
	entity->Variable.field_index = field_src_index;
	entity->flags |= EntityFlag_Field;
	entity->flags |= EntityFlag_ArrayElem;
	entity->state = EntityState_Resolved;
	return entity;
}

Entity *alloc_entity_procedure(Scope *scope, Token token, Type *signature_type, u64 tags) {
	Entity *entity = alloc_entity(Entity_Procedure, scope, token, signature_type);
	entity->Procedure.tags = tags;
	return entity;
}

Entity *alloc_entity_proc_group(Scope *scope, Token token, Type *type) {
	Entity *entity = alloc_entity(Entity_ProcGroup, scope, token, type);
	return entity;
}

Entity *alloc_entity_builtin(Scope *scope, Token token, Type *type, i32 id) {
	Entity *entity = alloc_entity(Entity_Builtin, scope, token, type);
	entity->Builtin.id = id;
	entity->state = EntityState_Resolved;
	return entity;
}

Entity *alloc_entity_import_name(Scope *scope, Token token, Type *type,
                                 String path, String name, Scope *import_scope) {
	Entity *entity = alloc_entity(Entity_ImportName, scope, token, type);
	entity->ImportName.path = path;
	entity->ImportName.name = name;
	entity->ImportName.scope = import_scope;
	entity->state = EntityState_Resolved; // TODO(bill): Is this correct?
	return entity;
}

Entity *alloc_entity_library_name(Scope *scope, Token token, Type *type,
                                  Slice<String> paths, String name) {
	Entity *entity = alloc_entity(Entity_LibraryName, scope, token, type);
	entity->LibraryName.paths = paths;
	entity->LibraryName.name = name;
	entity->state = EntityState_Resolved; // TODO(bill): Is this correct?
	return entity;
}

Entity *alloc_entity_nil(String name, Type *type) {
	Entity *entity = alloc_entity(Entity_Nil, nullptr, make_token_ident(name), type);
	return entity;
}

Entity *alloc_entity_label(Scope *scope, Token token, Type *type, Ast *node, Ast *parent) {
	Entity *entity = alloc_entity(Entity_Label, scope, token, type);
	entity->Label.node = node;
	entity->Label.parent = parent;
	entity->state = EntityState_Resolved;
	return entity;
}

Entity *alloc_entity_dummy_variable(Scope *scope, Token token) {
	token.string = str_lit("_");
	return alloc_entity_variable(scope, token, nullptr);
}

Entity *entity_from_expr(Ast *expr);

Entity *strip_entity_wrapping(Entity *e) {
	if (e == nullptr) {
		return nullptr;
	}
	if (e->kind != Entity_Constant) {
		return e;
	}
	if (e->Constant.value.kind == ExactValue_Procedure) {
		return strip_entity_wrapping(e->Constant.value.value_procedure);
	}
	return e;
}

Entity *strip_entity_wrapping(Ast *expr) {
	Entity *e = entity_from_expr(expr);
	return strip_entity_wrapping(e);
}
<commit_msg>Make `global_entity_id` atomic<commit_after>struct Scope;
struct Checker;
struct Type;
struct DeclInfo;
struct lbModule;
struct lbProcedure;

#define ENTITY_KINDS \
	ENTITY_KIND(Invalid) \
	ENTITY_KIND(Constant) \
	ENTITY_KIND(Variable) \
	ENTITY_KIND(TypeName) \
	ENTITY_KIND(Procedure) \
	ENTITY_KIND(ProcGroup) \
	ENTITY_KIND(Builtin) \
	ENTITY_KIND(ImportName) \
	ENTITY_KIND(LibraryName) \
	ENTITY_KIND(Nil) \
	ENTITY_KIND(Label)

enum EntityKind {
#define ENTITY_KIND(k) GB_JOIN2(Entity_, k),
	ENTITY_KINDS
#undef ENTITY_KIND
	Entity_Count,
};

String const entity_strings[] = {
#define ENTITY_KIND(k) {cast(u8 *)#k, gb_size_of(#k)-1},
	ENTITY_KINDS
#undef ENTITY_KIND
};

enum EntityFlag : u64 {
	EntityFlag_Visited       = 1ull<<0,
	EntityFlag_Used          = 1ull<<1,
	EntityFlag_Using         = 1ull<<2,
	EntityFlag_Field         = 1ull<<3,
	EntityFlag_Param         = 1ull<<4,
	EntityFlag_Result        = 1ull<<5,
	EntityFlag_ArrayElem     = 1ull<<6,
	EntityFlag_ArraySwizzle  = 1ull<<7,
	EntityFlag_Ellipsis      = 1ull<<8,
	EntityFlag_NoAlias       = 1ull<<9,
	EntityFlag_TypeField     = 1ull<<10,
	EntityFlag_Value         = 1ull<<11,
	EntityFlag_Sret          = 1ull<<12,
	EntityFlag_ByVal         = 1ull<<13,
	EntityFlag_BitFieldValue = 1ull<<14,
	EntityFlag_PolyConst     = 1ull<<15,
	EntityFlag_NotExported   = 1ull<<16,
	EntityFlag_ConstInput    = 1ull<<17,

	EntityFlag_Static        = 1ull<<18,

	EntityFlag_ImplicitReference = 1ull<<19, // NOTE(bill): equivalent to `const &` in C++

	EntityFlag_SoaPtrField   = 1ull<<20, // to allow s.x[0] where `s.x` is a pointer rather than a slice

	EntityFlag_ProcBodyChecked = 1ull<<21,

	EntityFlag_CVarArg       = 1ull<<22,
	EntityFlag_AutoCast      = 1ull<<23,
	EntityFlag_AnyInt        = 1ull<<24,

	EntityFlag_Disabled      = 1ull<<25,
	EntityFlag_Cold          = 1ull<<26, // procedure is rarely called

	EntityFlag_Lazy          = 1ull<<27, // Lazily type checked

	EntityFlag_Test          = 1ull<<30,

	EntityFlag_Overridden    = 1ull<<63,

};

enum EntityState : u32 {
	EntityState_Unresolved = 0,
	EntityState_InProgress = 1,
	EntityState_Resolved   = 2,
};

enum ParameterValueKind {
	ParameterValue_Invalid,
	ParameterValue_Constant,
	ParameterValue_Nil,
	ParameterValue_Location,
	ParameterValue_Value,
};

struct ParameterValue {
	ParameterValueKind kind;
	Ast *original_ast_expr;
	union {
		ExactValue value;
		Ast *ast_value;
	};
};

enum EntityConstantFlags : u32 {
	EntityConstantFlag_ImplicitEnumValue = 1<<0,
};

enum ProcedureOptimizationMode : u32 {
	ProcedureOptimizationMode_Default,
	ProcedureOptimizationMode_None,
	ProcedureOptimizationMode_Minimal,
	ProcedureOptimizationMode_Size,
	ProcedureOptimizationMode_Speed,
};

// An Entity is a named "thing" in the language
struct Entity {
	EntityKind  kind;
	u64         id;
	std::atomic<u64>         flags;
	std::atomic<EntityState> state;
	Token       token;
	Scope *     scope;
	Type *      type;
	std::atomic<Ast *> identifier; // Can be nullptr
	DeclInfo *  decl_info;
	DeclInfo *  parent_proc_decl; // nullptr if in file/global scope
	AstFile *   file;
	AstPackage *pkg;

	// TODO(bill): Cleanup how `using` works for entities
	Entity *    using_parent;
	Ast *       using_expr;

	Entity *    aliased_of;

	lbModule *   code_gen_module;
	lbProcedure *code_gen_procedure;

	u64         order_in_src;
	String      deprecated_message;
	String      warning_message;

	// IMPORTANT NOTE(bill): This must be a discriminated union because of patching
	// later entity kinds
	union {
		struct {
			u8 start;
		} Dummy;
		struct {
			ExactValue value;
			ParameterValue param_value;
			u32 flags;
		} Constant;
		struct {
			Ast *init_expr; // only used for some variables within procedure bodies
			i32        field_index;
			i32        field_src_index;

			ParameterValue param_value;
			Ast *          param_expr;

			String     thread_local_model;
			Entity *   foreign_library;
			Ast *      foreign_library_ident;
			String     link_name;
			String     link_prefix;
			String     link_section;
			bool       is_foreign;
			bool       is_export;
		} Variable;
		struct {
			Type * type_parameter_specialization;
			String ir_mangled_name;
			bool   is_type_alias;
		} TypeName;
		struct {
			u64     tags;
			Entity *foreign_library;
			Ast *   foreign_library_ident;
			String  link_name;
			String  link_prefix;
			DeferredProcedure deferred_procedure;
			bool    is_foreign;
			bool    is_export;
			ProcedureOptimizationMode optimization_mode;
		} Procedure;
		struct {
			Array<Entity *> entities;
		} ProcGroup;
		struct {
			i32 id;
		} Builtin;
		struct {
			String path;
			String name;
			Scope *scope;
		} ImportName;
		struct {
			Slice<String> paths;
			String name;
		} LibraryName;
		i32 Nil;
		struct {
			String name;
			Ast *node;
			Ast *parent;
		} Label;
	};
};

bool is_entity_kind_exported(EntityKind kind, bool allow_builtin = false) {
	switch (kind) {
	case Entity_Builtin:
		return allow_builtin;
	case Entity_ImportName:
	case Entity_LibraryName:
	case Entity_Nil:
		return false;
	}
	return true;
}

bool is_entity_exported(Entity *e, bool allow_builtin = false) {
	// TODO(bill): Determine the actual exportation rules for imports of entities
	GB_ASSERT(e != nullptr);
	if (!is_entity_kind_exported(e->kind, allow_builtin)) {
		return false;
	}

	if (e->flags & EntityFlag_NotExported) {
		return false;
	}
	if (e->file != nullptr && (e->file->flags & AstFile_IsPrivate) != 0) {
		return false;
	}

	String name = e->token.string;
	switch (name.len) {
	case 0: return false;
	case 1: return name[0] != '_';
	}
	return true;
}

bool entity_has_deferred_procedure(Entity *e) {
	GB_ASSERT(e != nullptr);
	if (e->kind == Entity_Procedure) {
		return e->Procedure.deferred_procedure.entity != nullptr;
	}
	return false;
}

gb_global std::atomic<u64> global_entity_id = 0;

Entity *alloc_entity(EntityKind kind, Scope *scope, Token token, Type *type) {
	gbAllocator a = permanent_allocator();
	Entity *entity = gb_alloc_item(a, Entity);
	entity->kind   = kind;
	entity->state  = EntityState_Unresolved;
	entity->scope  = scope;
	entity->token  = token;
	entity->type   = type;
	entity->id     = 1 + global_entity_id.fetch_add(1);
	return entity;
}

Entity *alloc_entity_variable(Scope *scope, Token token, Type *type, EntityState state = EntityState_Unresolved) {
	Entity *entity = alloc_entity(Entity_Variable, scope, token, type);
	entity->state = state;
	return entity;
}

Entity *alloc_entity_using_variable(Entity *parent, Token token, Type *type, Ast *using_expr) {
	GB_ASSERT(parent != nullptr);
	token.pos = parent->token.pos;
	Entity *entity = alloc_entity(Entity_Variable, parent->scope, token, type);
	entity->using_parent = parent;
	entity->parent_proc_decl = parent->parent_proc_decl;
	entity->using_expr = using_expr;
	entity->flags |= EntityFlag_Using;
	entity->flags |= EntityFlag_Used;
	entity->state = EntityState_Resolved;
	return entity;
}

Entity *alloc_entity_constant(Scope *scope, Token token, Type *type, ExactValue value) {
	Entity *entity = alloc_entity(Entity_Constant, scope, token, type);
	entity->Constant.value = value;
	return entity;
}

Entity *alloc_entity_type_name(Scope *scope, Token token, Type *type, EntityState state = EntityState_Unresolved) {
	Entity *entity = alloc_entity(Entity_TypeName, scope, token, type);
	entity->state = state;
	return entity;
}

Entity *alloc_entity_param(Scope *scope, Token token, Type *type, bool is_using, bool is_value) {
	Entity *entity = alloc_entity_variable(scope, token, type);
	entity->flags |= EntityFlag_Used;
	entity->flags |= EntityFlag_Param;
	entity->state = EntityState_Resolved;
	if (is_using) entity->flags |= EntityFlag_Using;
	if (is_value) entity->flags |= EntityFlag_Value;
	return entity;
}

Entity *alloc_entity_const_param(Scope *scope, Token token, Type *type, ExactValue value, bool poly_const) {
	Entity *entity = alloc_entity_constant(scope, token, type, value);
	entity->flags |= EntityFlag_Used;
	if (poly_const) entity->flags |= EntityFlag_PolyConst;
	entity->flags |= EntityFlag_Param;
	return entity;
}

Entity *alloc_entity_field(Scope *scope, Token token, Type *type, bool is_using, i32 field_src_index, EntityState state = EntityState_Unresolved) {
	Entity *entity = alloc_entity_variable(scope, token, type);
	entity->Variable.field_src_index = field_src_index;
	entity->Variable.field_index = field_src_index;
	if (is_using) entity->flags |= EntityFlag_Using;
	entity->flags |= EntityFlag_Field;
	entity->state = state;
	return entity;
}

Entity *alloc_entity_array_elem(Scope *scope, Token token, Type *type, i32 field_src_index) {
	Entity *entity = alloc_entity_variable(scope, token, type);
	entity->Variable.field_src_index = field_src_index;
	entity->Variable.field_index = field_src_index;
	entity->flags |= EntityFlag_Field;
	entity->flags |= EntityFlag_ArrayElem;
	entity->state = EntityState_Resolved;
	return entity;
}

Entity *alloc_entity_procedure(Scope *scope, Token token, Type *signature_type, u64 tags) {
	Entity *entity = alloc_entity(Entity_Procedure, scope, token, signature_type);
	entity->Procedure.tags = tags;
	return entity;
}

Entity *alloc_entity_proc_group(Scope *scope, Token token, Type *type) {
	Entity *entity = alloc_entity(Entity_ProcGroup, scope, token, type);
	return entity;
}

Entity *alloc_entity_builtin(Scope *scope, Token token, Type *type, i32 id) {
	Entity *entity = alloc_entity(Entity_Builtin, scope, token, type);
	entity->Builtin.id = id;
	entity->state = EntityState_Resolved;
	return entity;
}

Entity *alloc_entity_import_name(Scope *scope, Token token, Type *type,
                                 String path, String name, Scope *import_scope) {
	Entity *entity = alloc_entity(Entity_ImportName, scope, token, type);
	entity->ImportName.path = path;
	entity->ImportName.name = name;
	entity->ImportName.scope = import_scope;
	entity->state = EntityState_Resolved; // TODO(bill): Is this correct?
	return entity;
}

Entity *alloc_entity_library_name(Scope *scope, Token token, Type *type,
                                  Slice<String> paths, String name) {
	Entity *entity = alloc_entity(Entity_LibraryName, scope, token, type);
	entity->LibraryName.paths = paths;
	entity->LibraryName.name = name;
	entity->state = EntityState_Resolved; // TODO(bill): Is this correct?
	return entity;
}

Entity *alloc_entity_nil(String name, Type *type) {
	Entity *entity = alloc_entity(Entity_Nil, nullptr, make_token_ident(name), type);
	return entity;
}

Entity *alloc_entity_label(Scope *scope, Token token, Type *type, Ast *node, Ast *parent) {
	Entity *entity = alloc_entity(Entity_Label, scope, token, type);
	entity->Label.node = node;
	entity->Label.parent = parent;
	entity->state = EntityState_Resolved;
	return entity;
}

Entity *alloc_entity_dummy_variable(Scope *scope, Token token) {
	token.string = str_lit("_");
	return alloc_entity_variable(scope, token, nullptr);
}

Entity *entity_from_expr(Ast *expr);

Entity *strip_entity_wrapping(Entity *e) {
	if (e == nullptr) {
		return nullptr;
	}
	if (e->kind != Entity_Constant) {
		return e;
	}
	if (e->Constant.value.kind == ExactValue_Procedure) {
		return strip_entity_wrapping(e->Constant.value.value_procedure);
	}
	return e;
}

Entity *strip_entity_wrapping(Ast *expr) {
	Entity *e = entity_from_expr(expr);
	return strip_entity_wrapping(e);
}
<|endoftext|>


<commit_before>//
// PROJECT:         Aspia
// FILE:            codec/pixel_translator.h
// LICENSE:         GNU General Public License 3
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "codec/pixel_translator.h"

namespace aspia {

namespace {

template<int source_bpp, int target_bpp>
class PixelTranslatorT : public PixelTranslator
{
public:
    PixelTranslatorT(const PixelFormat& source_format, const PixelFormat& target_format)
        : source_format_(source_format),
          target_format_(target_format)
    {
        red_table_ = std::make_unique<quint32[]>(source_format_.redMax() + 1);
        green_table_ = std::make_unique<quint32[]>(source_format_.greenMax() + 1);
        blue_table_ = std::make_unique<quint32[]>(source_format_.blueMax() + 1);

        for (quint32 i = 0; i <= source_format_.redMax(); ++i)
        {
            red_table_[i] = ((i * target_format_.redMax() + source_format_.redMax() / 2) /
                             source_format_.redMax()) << target_format_.redShift();
        }

        for (quint32 i = 0; i <= source_format_.greenMax(); ++i)
        {
            green_table_[i] = ((i * target_format_.greenMax() + source_format_.greenMax() / 2) /
                               source_format_.greenMax()) << target_format_.greenShift();
        }

        for (quint32 i = 0; i <= source_format_.blueMax(); ++i)
        {
            blue_table_[i] = ((i * target_format_.blueMax() + source_format_.blueMax() / 2) /
                              source_format_.blueMax()) << target_format_.blueShift();
        }
    }

    ~PixelTranslatorT() = default;

    void translate(const quint8* src, int src_stride,
                   quint8* dst, int dst_stride,
                   int width, int height) override
    {
        src_stride -= width * source_bpp;
        dst_stride -= width * target_bpp;

        for (int y = 0; y < height; ++y)
        {
            for (int x = 0; x < width; ++x)
            {
                quint32 red;
                quint32 green;
                quint32 blue;

                if constexpr (source_bpp == 4)
                {
                    red = red_table_[
                        *(quint32*) src >> source_format_.redShift() & source_format_.redMax()];
                    green = green_table_[
                        *(quint32*) src >> source_format_.greenShift() & source_format_.greenMax()];
                    blue = blue_table_[
                        *(quint32*) src >> source_format_.blueShift() & source_format_.blueMax()];
                }
                else if constexpr (source_bpp == 2)
                {
                    red = red_table_[
                        *(quint16*) src >> source_format_.redShift() & source_format_.redMax()];
                    green = green_table_[
                        *(quint16*) src >> source_format_.greenShift() & source_format_.greenMax()];
                    blue = blue_table_[
                        *(quint16*) src >> source_format_.blueShift() & source_format_.blueMax()];
                }
                else if constexpr (source_bpp == 1)
                {
                    red = red_table_[
                        *(quint8*) src >> source_format_.redShift() & source_format_.redMax()];
                    green = green_table_[
                        *(quint8*) src >> source_format_.greenShift() & source_format_.greenMax()];
                    blue = blue_table_[
                        *(quint8*) src >> source_format_.blueShift() & source_format_.blueMax()];
                }

                if constexpr (target_bpp == 4)
                    *(quint32*) dst = static_cast<quint32>(red | green | blue);
                else if constexpr (target_bpp == 2)
                    *(quint16*) dst = static_cast<quint16>(red | green | blue);
                else if constexpr (target_bpp == 1)
                    *(quint8*) dst = static_cast<quint8>(red | green | blue);

                src += source_bpp;
                dst += target_bpp;
            }

            src += src_stride;
            dst += dst_stride;
        }
    }

private:
    std::unique_ptr<quint32[]> red_table_;
    std::unique_ptr<quint32[]> green_table_;
    std::unique_ptr<quint32[]> blue_table_;

    PixelFormat source_format_;
    PixelFormat target_format_;

    Q_DISABLE_COPY(PixelTranslatorT)
};

} // namespace

// static
std::unique_ptr<PixelTranslator> PixelTranslator::create(const PixelFormat& source_format,
                                                         const PixelFormat& target_format)
{
    switch (target_format.bytesPerPixel())
    {
        case 4:
        {
            switch (source_format.bytesPerPixel())
            {
                case 4:
                    return std::make_unique<PixelTranslatorT<4, 4>>(source_format, target_format);

                case 2:
                    return std::make_unique<PixelTranslatorT<2, 4>>(source_format, target_format);

                case 1:
                    return std::make_unique<PixelTranslatorT<1, 4>>(source_format, target_format);
            }
        }
        break;

        case 2:
        {
            switch (source_format.bytesPerPixel())
            {
                case 4:
                    return std::make_unique<PixelTranslatorT<4, 2>>(source_format, target_format);

                case 2:
                    return std::make_unique<PixelTranslatorT<2, 2>>(source_format, target_format);

                case 1:
                    return std::make_unique<PixelTranslatorT<1, 2>>(source_format, target_format);
            }
        }
        break;

        case 1:
        {
            switch (source_format.bytesPerPixel())
            {
                case 4:
                    return std::make_unique<PixelTranslatorT<4, 1>>(source_format, target_format);

                case 2:
                    return std::make_unique<PixelTranslatorT<2, 1>>(source_format, target_format);

                case 1:
                    return std::make_unique<PixelTranslatorT<1, 1>>(source_format, target_format);
            }
        }
        break;
    }

    return nullptr;
}

} // namespace aspia
<commit_msg>- Implemented PixelTranslatorFrom16bppT class (optimized for translation from 16bpp).<commit_after>//
// PROJECT:         Aspia
// FILE:            codec/pixel_translator.h
// LICENSE:         GNU General Public License 3
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "codec/pixel_translator.h"

namespace aspia {

namespace {

template<int kSourceBpp, int kTargetBpp>
class PixelTranslatorT : public PixelTranslator
{
public:
    PixelTranslatorT(const PixelFormat& source_format, const PixelFormat& target_format)
        : source_format_(source_format),
          target_format_(target_format)
    {
        red_table_ = std::make_unique<quint32[]>(source_format_.redMax() + 1);
        green_table_ = std::make_unique<quint32[]>(source_format_.greenMax() + 1);
        blue_table_ = std::make_unique<quint32[]>(source_format_.blueMax() + 1);

        for (quint32 i = 0; i <= source_format_.redMax(); ++i)
        {
            red_table_[i] = ((i * target_format_.redMax() + source_format_.redMax() / 2) /
                             source_format_.redMax()) << target_format_.redShift();
        }

        for (quint32 i = 0; i <= source_format_.greenMax(); ++i)
        {
            green_table_[i] = ((i * target_format_.greenMax() + source_format_.greenMax() / 2) /
                               source_format_.greenMax()) << target_format_.greenShift();
        }

        for (quint32 i = 0; i <= source_format_.blueMax(); ++i)
        {
            blue_table_[i] = ((i * target_format_.blueMax() + source_format_.blueMax() / 2) /
                              source_format_.blueMax()) << target_format_.blueShift();
        }
    }

    ~PixelTranslatorT() = default;

    void translate(const quint8* src, int src_stride,
                   quint8* dst, int dst_stride,
                   int width, int height) override
    {
        src_stride -= width * kSourceBpp;
        dst_stride -= width * kTargetBpp;

        for (int y = 0; y < height; ++y)
        {
            for (int x = 0; x < width; ++x)
            {
                quint32 red;
                quint32 green;
                quint32 blue;

                if constexpr (kSourceBpp == 4)
                {
                    red = red_table_[
                        *(quint32*) src >> source_format_.redShift() & source_format_.redMax()];
                    green = green_table_[
                        *(quint32*) src >> source_format_.greenShift() & source_format_.greenMax()];
                    blue = blue_table_[
                        *(quint32*) src >> source_format_.blueShift() & source_format_.blueMax()];
                }
                else if constexpr (kSourceBpp == 2)
                {
                    red = red_table_[
                        *(quint16*) src >> source_format_.redShift() & source_format_.redMax()];
                    green = green_table_[
                        *(quint16*) src >> source_format_.greenShift() & source_format_.greenMax()];
                    blue = blue_table_[
                        *(quint16*) src >> source_format_.blueShift() & source_format_.blueMax()];
                }
                else if constexpr (kSourceBpp == 1)
                {
                    red = red_table_[
                        *(quint8*) src >> source_format_.redShift() & source_format_.redMax()];
                    green = green_table_[
                        *(quint8*) src >> source_format_.greenShift() & source_format_.greenMax()];
                    blue = blue_table_[
                        *(quint8*) src >> source_format_.blueShift() & source_format_.blueMax()];
                }

                if constexpr (kTargetBpp == 4)
                    *(quint32*) dst = static_cast<quint32>(red | green | blue);
                else if constexpr (kTargetBpp == 2)
                    *(quint16*) dst = static_cast<quint16>(red | green | blue);
                else if constexpr (kTargetBpp == 1)
                    *(quint8*) dst = static_cast<quint8>(red | green | blue);

                src += kSourceBpp;
                dst += kTargetBpp;
            }

            src += src_stride;
            dst += dst_stride;
        }
    }

private:
    std::unique_ptr<quint32[]> red_table_;
    std::unique_ptr<quint32[]> green_table_;
    std::unique_ptr<quint32[]> blue_table_;

    PixelFormat source_format_;
    PixelFormat target_format_;

    Q_DISABLE_COPY(PixelTranslatorT)
};

template<int kTargetBpp>
class PixelTranslatorFrom16bppT : public PixelTranslator
{
public:
    PixelTranslatorFrom16bppT(const PixelFormat& source_format, const PixelFormat& target_format)
        : source_format_(source_format),
          target_format_(target_format)
    {
        quint32 source_red_mask = source_format.redMax() << source_format.redShift();
        quint32 source_green_mask = source_format.greenMax() << source_format.greenShift();
        quint32 source_blue_mask = source_format.blueMax() << source_format.blueShift();

        for (quint32 i = 0; i < kTableSize; ++i)
        {
            quint32 source_red = (i & source_red_mask) >> source_format.redShift();
            quint32 source_green = (i & source_green_mask) >> source_format.greenShift();
            quint32 source_blue = (i & source_blue_mask) >> source_format.blueShift();

            quint32 target_red =
                (source_red * target_format.redMax() / source_format.redMax()) << target_format.redShift();
            quint32 target_green =
                (source_green * target_format.greenMax() / source_format.greenMax()) << target_format.greenShift();
            quint32 target_blue =
                (source_blue * target_format.blueMax() / source_format.blueMax()) << target_format.blueShift();

            table_[i] = target_red | target_green | target_blue;
        }
    }

    ~PixelTranslatorFrom16bppT() = default;

    void translate(const quint8* src, int src_stride,
                   quint8* dst, int dst_stride,
                   int width, int height) override
    {
        src_stride -= width * kSourceBpp;
        dst_stride -= width * kTargetBpp;

        for (int y = 0; y < height; ++y)
        {
            for (int x = 0; x < width; ++x)
            {
                quint32 target_pixel = table_[*(quint16*)src];

                if constexpr (kTargetBpp == 4)
                    *(quint32*)dst = static_cast<quint32>(target_pixel);
                else if constexpr (kTargetBpp == 2)
                    *(quint16*)dst = static_cast<quint16>(target_pixel);
                else if constexpr (kTargetBpp == 1)
                    *(quint8*)dst = static_cast<quint8>(target_pixel);

                src += kSourceBpp;
                dst += kTargetBpp;
            }

            src += src_stride;
            dst += dst_stride;
        }
    }

private:
    static const size_t kTableSize = 65536;
    static const int kSourceBpp = 2;

    quint32 table_[kTableSize];

    PixelFormat source_format_;
    PixelFormat target_format_;

    Q_DISABLE_COPY(PixelTranslatorFrom16bppT)
};

} // namespace

// static
std::unique_ptr<PixelTranslator> PixelTranslator::create(const PixelFormat& source_format,
                                                         const PixelFormat& target_format)
{
    switch (target_format.bytesPerPixel())
    {
        case 4:
        {
            switch (source_format.bytesPerPixel())
            {
                case 4:
                    return std::make_unique<PixelTranslatorT<4, 4>>(source_format, target_format);

                case 2:
                    return std::make_unique<PixelTranslatorFrom16bppT<4>>(source_format, target_format);

                case 1:
                    return std::make_unique<PixelTranslatorT<1, 4>>(source_format, target_format);
            }
        }
        break;

        case 2:
        {
            switch (source_format.bytesPerPixel())
            {
                case 4:
                    return std::make_unique<PixelTranslatorT<4, 2>>(source_format, target_format);

                case 2:
                    return std::make_unique<PixelTranslatorFrom16bppT<2>>(source_format, target_format);

                case 1:
                    return std::make_unique<PixelTranslatorT<1, 2>>(source_format, target_format);
            }
        }
        break;

        case 1:
        {
            switch (source_format.bytesPerPixel())
            {
                case 4:
                    return std::make_unique<PixelTranslatorT<4, 1>>(source_format, target_format);

                case 2:
                    return std::make_unique<PixelTranslatorFrom16bppT<1>>(source_format, target_format);

                case 1:
                    return std::make_unique<PixelTranslatorT<1, 1>>(source_format, target_format);
            }
        }
        break;
    }

    return nullptr;
}

} // namespace aspia
<|endoftext|>