<commit_before>#include "stdafx.h"
#include "Player.h"
#include "Math.h"
#include "PlayerManager.h"

Player::Player(void):mPosition(0,0),mPlayerState(PLAYER_STATE_IDLE)
{
}

Player::Player(int id, ClientSession* client):mHP(100),mDamage(5),mPlayerState(PLAYER_STATE_IDLE),mMovedInfo(0),mAttackRange(12),mRadius(24)
{

	mPlayerId = id;
	mClient = client;

	while(1)
	{
		float x = rand() % (GGameMap->GetWidth() * 64);
		float y = rand() % (GGameMap->GetHeight() * 64);
		bool isOk = true;
		for(float _x = x - mRadius; _x <= x + mRadius; _x += mRadius)
		{
			for(float _y = y - mRadius; _y <= y + mRadius; _y += mRadius)
			{
				if(GGameMap->isValidTile(Point(x,y)) != true)
				{
					isOk = false;
					break;
				}
			}
			if(isOk == false)
				break;
		}
		if(isOk == true)
		{
			mPosition = Point(x,y);
			break;
		}
	}
}

Player::~Player(void)
{
}

void Player::TransState(short state)
{
	switch (state)
	{
	case PLAYER_STATE_IDLE:
		{
			mPlayerState = state;

			GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
			outPacket.mMyPlayerInfo = this->GetPlayerInfo();
			mClient->Broadcast(&outPacket);

		}
		break;
	case PLAYER_STATE_WALK:
		{
			Point willGoPosition = GetPosition();
			if ( mGameKeyStates.leftDirectKey ==  KEYSTATE_PRESSED )willGoPosition = willGoPosition + Point( -1.f, 0.f ) * mDTime * 100.f;
			if ( mGameKeyStates.rightDirectKey == KEYSTATE_PRESSED )willGoPosition = willGoPosition + Point( +1.f, 0.f ) * mDTime * 100.f;
			if ( mGameKeyStates.upDirectKey == KEYSTATE_PRESSED )	willGoPosition = willGoPosition + Point( 0.f, -1.f ) * mDTime * 100.f;
			if ( mGameKeyStates.downDirectKey == KEYSTATE_PRESSED )	willGoPosition = willGoPosition + Point( 0.f, 1.f ) * mDTime * 100.f;

			if ( GGameMap->isValidTile(willGoPosition) == false )
			{
				//ϱ walk ȯ .
				break;
			}
			if(mPlayerState == PLAYER_STATE_IDLE)
			{
				mPlayerState = state;
				mMovedInfo = -1;
				GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
				outPacket.mMyPlayerInfo = this->GetPlayerInfo();
				mClient->Broadcast(&outPacket);
			}
		}
		break;
	case PLAYER_STATE_ATTACK:
		{
			if(mPlayerState == PLAYER_STATE_IDLE ||
				mPlayerState == PLAYER_STATE_WALK)
			{
				mPlayerState = state;

				GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
				outPacket.mMyPlayerInfo = this->GetPlayerInfo();
				mClient->Broadcast(&outPacket);
			}

		}
		break;
	case PLAYER_STATE_DIE:
		{
			mResponTime = 5.f;
			mPlayerState = state;

			GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
			outPacket.mMyPlayerInfo = this->GetPlayerInfo();
			mClient->Broadcast(&outPacket);
		}
		break;
	case PLAYER_STATE_TYPESKILL:
		{
			if(mPlayerState == PLAYER_STATE_IDLE ||
				mPlayerState == PLAYER_STATE_WALK)
			{
				mPlayerState = state;

				GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
				outPacket.mMyPlayerInfo = this->GetPlayerInfo();
				mClient->Broadcast(&outPacket);
			}
		}
	case PLAYER_STATE_USERSKILL:
		{
			if(mPlayerState == PLAYER_STATE_IDLE ||
				mPlayerState == PLAYER_STATE_WALK)
			{
				mPlayerState = state;

				GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
				outPacket.mMyPlayerInfo = this->GetPlayerInfo();
				mClient->Broadcast(&outPacket);
			}
		}
		break;
	default:
		break;
	}
}

void Player::Update( float dTime)
{
	printf("%f\n",dTime);
	mDTime = dTime;
	switch (mPlayerState)
	{
	case PLAYER_STATE_IDLE:
		{
			if( mGameKeyStates.typeActiveSkillKey == KEYSTATE_PRESSED)
			{
				TransState(PLAYER_STATE_TYPESKILL);
				break;
			}
			if( mGameKeyStates.userActiveSkillKey == KEYSTATE_PRESSED)
			{
				TransState(PLAYER_STATE_USERSKILL);
				break;
			}
			if( mGameKeyStates.attackKey == KEYSTATE_PRESSED )
			{
				TransState(PLAYER_STATE_ATTACK);
				break;
			}
			else if ( mGameKeyStates.leftDirectKey ==  KEYSTATE_PRESSED
				|| mGameKeyStates.rightDirectKey == KEYSTATE_PRESSED
				|| mGameKeyStates.upDirectKey == KEYSTATE_PRESSED
				|| mGameKeyStates.downDirectKey == KEYSTATE_PRESSED )
			{
				TransState(PLAYER_STATE_WALK);
			}else if ( mGameKeyStates.typeActiveSkillKey == KEYSTATE_PRESSED)
				TransState(PLAYER_STATE_TYPESKILL);
		}
		break;
	case PLAYER_STATE_WALK:
		{
			if( mGameKeyStates.typeActiveSkillKey == KEYSTATE_PRESSED)
			{
				TransState(PLAYER_STATE_TYPESKILL);
				break;
			}
			if( mGameKeyStates.userActiveSkillKey == KEYSTATE_PRESSED)
			{
				TransState(PLAYER_STATE_USERSKILL);
				break;
			}
			if( mGameKeyStates.attackKey == KEYSTATE_PRESSED )
			{
				TransState(PLAYER_STATE_ATTACK);
				break;
			}
			//Move myPlayer with Game Key States.
			//Check Moving Input, and set Position to d

			// ٲ üũ
			int moveInfo = 0;
			if ( mGameKeyStates.leftDirectKey ==  KEYSTATE_PRESSED ) moveInfo |= 4;
			if ( mGameKeyStates.rightDirectKey == KEYSTATE_PRESSED ) moveInfo |= 2;
			if ( mGameKeyStates.upDirectKey == KEYSTATE_PRESSED	)	moveInfo |= 1;
			if ( mGameKeyStates.downDirectKey == KEYSTATE_PRESSED )	moveInfo |= 8;

			//  ϴ  map ̵  ̴?
			Point willGoPosition = GetPosition();
			if ( mGameKeyStates.leftDirectKey ==  KEYSTATE_PRESSED )willGoPosition = willGoPosition + Point( -1.f, 0.f ) * (mRadius + dTime * 100.f);
			if ( mGameKeyStates.rightDirectKey == KEYSTATE_PRESSED )willGoPosition = willGoPosition + Point( +1.f, 0.f ) * (mRadius + dTime * 100.f);
			if ( mGameKeyStates.upDirectKey == KEYSTATE_PRESSED )	willGoPosition = willGoPosition + Point( 0.f, -1.f ) * (mRadius + dTime * 100.f);
			if ( mGameKeyStates.downDirectKey == KEYSTATE_PRESSED )	willGoPosition = willGoPosition + Point( 0.f, 1.f ) * (mRadius + dTime * 100.f);

			//wasd    Ȯ
			if ( mGameKeyStates.leftDirectKey ==  KEYSTATE_NOTPRESSED
				&& mGameKeyStates.rightDirectKey == KEYSTATE_NOTPRESSED
				&& mGameKeyStates.upDirectKey == KEYSTATE_NOTPRESSED
				&& mGameKeyStates.downDirectKey == KEYSTATE_NOTPRESSED )
			{
				TransState(PLAYER_STATE_IDLE);
				break;
			}

			if ( GGameMap->isValidTile(willGoPosition) == false )
			{
				//ϱ Idle· .
				TransState(PLAYER_STATE_IDLE);
				break;
			}
			//׸   ʴ , Ʒ SetPosition ̵ϰ ͸  Ǹ Ŭ 忡  ó ...
			SetPosition(willGoPosition);

			// ٸ  ̵ߴ?
			if( mMovedInfo != -1 && moveInfo != mMovedInfo)
			{
				//ٲ key .
				GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
				outPacket.mMyPlayerInfo = this->GetPlayerInfo();
				mClient->Broadcast(&outPacket);
			}

			mMovedInfo = moveInfo;

		}
		break;
	case PLAYER_STATE_ATTACK:
		{
			Point AttackPoint = mPosition + Point(cos(mRotation) * mAttackRange,sin(mRotation) * mAttackRange);
			std::map<int,Player*> players = GPlayerManager->GetPlayers();
			for( std::map<int,Player*>::iterator it = players.begin(); it != players.end(); ++it )
			{
				Player* enemy = it->second;
				if(enemy == this)continue;

				if( Point().GetDistance( enemy->GetPosition(), AttackPoint ) < mAttackRange )
				{
					//ǰݵ
					enemy->Damaged(mHP);
				}
			}
			TransState(PLAYER_STATE_IDLE);
			break;
		}
		break;

	case PLAYER_STATE_DIE:
		{
			mResponTime -= dTime;
			if(mResponTime < 0)
			{
				//մϴ.
				while(1)
				{
					float x = rand() % (GGameMap->GetWidth() * 64);
					float y = rand() % (GGameMap->GetHeight() * 64);
					if(GGameMap->isValidTile(Point(x,y)) == true)
					{
						mPosition = Point(x,y);
						break;
					}
				}
				SetHP(100);
				TransState(PLAYER_STATE_IDLE);
				break;
			}
		}
		break;
	case PLAYER_STATE_TYPESKILL:
		{
			TransState(PLAYER_STATE_IDLE);
			break;
		}
		break;
	case PLAYER_STATE_USERSKILL:
		{
			TransState(PLAYER_STATE_IDLE);
			break;
		}
		break;
	default:
		break;
	}
}
void Player::Damaged(int damage)
{
	if(mHP < damage)
	{
		//׾
		TransState(PLAYER_STATE_DIE);
	}
	else
	{
		mHP-=damage;
		//  󸶶 εĳ
		HPUpdateResult outPacket = HPUpdateResult();
		outPacket.mPlayerId = mPlayerId;
		outPacket.mHP = mHP;
		mClient->Broadcast(&outPacket);
	}

}
PlayerInfo Player::GetPlayerInfo()
{
	PlayerInfo mPlayerInfo;
	mPlayerInfo.mGameKeyStates = mGameKeyStates;
	mPlayerInfo.mX = mPosition.x;
	mPlayerInfo.mY = mPosition.y;
	mPlayerInfo.mPlayerId = mPlayerId;
	mPlayerInfo.mAngle = mRotation;
	mPlayerInfo.mPlayerState = mPlayerState;
	mPlayerInfo.mHP = mHP;
	return mPlayerInfo;
}<commit_msg>업데이트 로그 제거 <commit_after>#include "stdafx.h"
#include "Player.h"
#include "Math.h"
#include "PlayerManager.h"

Player::Player(void):mPosition(0,0),mPlayerState(PLAYER_STATE_IDLE)
{
}

Player::Player(int id, ClientSession* client):mHP(100),mDamage(5),mPlayerState(PLAYER_STATE_IDLE),mMovedInfo(0),mAttackRange(12),mRadius(24)
{

	mPlayerId = id;
	mClient = client;

	while(1)
	{
		float x = rand() % (GGameMap->GetWidth() * 64);
		float y = rand() % (GGameMap->GetHeight() * 64);
		bool isOk = true;
		for(float _x = x - mRadius; _x <= x + mRadius; _x += mRadius)
		{
			for(float _y = y - mRadius; _y <= y + mRadius; _y += mRadius)
			{
				if(GGameMap->isValidTile(Point(x,y)) != true)
				{
					isOk = false;
					break;
				}
			}
			if(isOk == false)
				break;
		}
		if(isOk == true)
		{
			mPosition = Point(x,y);
			break;
		}
	}
}

Player::~Player(void)
{
}

void Player::TransState(short state)
{
	switch (state)
	{
	case PLAYER_STATE_IDLE:
		{
			mPlayerState = state;

			GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
			outPacket.mMyPlayerInfo = this->GetPlayerInfo();
			mClient->Broadcast(&outPacket);

		}
		break;
	case PLAYER_STATE_WALK:
		{
			Point willGoPosition = GetPosition();
			if ( mGameKeyStates.leftDirectKey ==  KEYSTATE_PRESSED )willGoPosition = willGoPosition + Point( -1.f, 0.f ) * mDTime * 100.f;
			if ( mGameKeyStates.rightDirectKey == KEYSTATE_PRESSED )willGoPosition = willGoPosition + Point( +1.f, 0.f ) * mDTime * 100.f;
			if ( mGameKeyStates.upDirectKey == KEYSTATE_PRESSED )	willGoPosition = willGoPosition + Point( 0.f, -1.f ) * mDTime * 100.f;
			if ( mGameKeyStates.downDirectKey == KEYSTATE_PRESSED )	willGoPosition = willGoPosition + Point( 0.f, 1.f ) * mDTime * 100.f;

			if ( GGameMap->isValidTile(willGoPosition) == false )
			{
				//ϱ walk ȯ .
				break;
			}
			if(mPlayerState == PLAYER_STATE_IDLE)
			{
				mPlayerState = state;
				mMovedInfo = -1;
				GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
				outPacket.mMyPlayerInfo = this->GetPlayerInfo();
				mClient->Broadcast(&outPacket);
			}
		}
		break;
	case PLAYER_STATE_ATTACK:
		{
			if(mPlayerState == PLAYER_STATE_IDLE ||
				mPlayerState == PLAYER_STATE_WALK)
			{
				mPlayerState = state;

				GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
				outPacket.mMyPlayerInfo = this->GetPlayerInfo();
				mClient->Broadcast(&outPacket);
			}

		}
		break;
	case PLAYER_STATE_DIE:
		{
			mResponTime = 5.f;
			mPlayerState = state;

			GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
			outPacket.mMyPlayerInfo = this->GetPlayerInfo();
			mClient->Broadcast(&outPacket);
		}
		break;
	case PLAYER_STATE_TYPESKILL:
		{
			if(mPlayerState == PLAYER_STATE_IDLE ||
				mPlayerState == PLAYER_STATE_WALK)
			{
				mPlayerState = state;

				GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
				outPacket.mMyPlayerInfo = this->GetPlayerInfo();
				mClient->Broadcast(&outPacket);
			}
		}
	case PLAYER_STATE_USERSKILL:
		{
			if(mPlayerState == PLAYER_STATE_IDLE ||
				mPlayerState == PLAYER_STATE_WALK)
			{
				mPlayerState = state;

				GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
				outPacket.mMyPlayerInfo = this->GetPlayerInfo();
				mClient->Broadcast(&outPacket);
			}
		}
		break;
	default:
		break;
	}
}

void Player::Update( float dTime)
{
	mDTime = dTime;
	switch (mPlayerState)
	{
	case PLAYER_STATE_IDLE:
		{
			if( mGameKeyStates.typeActiveSkillKey == KEYSTATE_PRESSED)
			{
				TransState(PLAYER_STATE_TYPESKILL);
				break;
			}
			if( mGameKeyStates.userActiveSkillKey == KEYSTATE_PRESSED)
			{
				TransState(PLAYER_STATE_USERSKILL);
				break;
			}
			if( mGameKeyStates.attackKey == KEYSTATE_PRESSED )
			{
				TransState(PLAYER_STATE_ATTACK);
				break;
			}
			else if ( mGameKeyStates.leftDirectKey ==  KEYSTATE_PRESSED
				|| mGameKeyStates.rightDirectKey == KEYSTATE_PRESSED
				|| mGameKeyStates.upDirectKey == KEYSTATE_PRESSED
				|| mGameKeyStates.downDirectKey == KEYSTATE_PRESSED )
			{
				TransState(PLAYER_STATE_WALK);
			}else if ( mGameKeyStates.typeActiveSkillKey == KEYSTATE_PRESSED)
				TransState(PLAYER_STATE_TYPESKILL);
		}
		break;
	case PLAYER_STATE_WALK:
		{
			if( mGameKeyStates.typeActiveSkillKey == KEYSTATE_PRESSED)
			{
				TransState(PLAYER_STATE_TYPESKILL);
				break;
			}
			if( mGameKeyStates.userActiveSkillKey == KEYSTATE_PRESSED)
			{
				TransState(PLAYER_STATE_USERSKILL);
				break;
			}
			if( mGameKeyStates.attackKey == KEYSTATE_PRESSED )
			{
				TransState(PLAYER_STATE_ATTACK);
				break;
			}
			//Move myPlayer with Game Key States.
			//Check Moving Input, and set Position to d

			// ٲ üũ
			int moveInfo = 0;
			if ( mGameKeyStates.leftDirectKey ==  KEYSTATE_PRESSED ) moveInfo |= 4;
			if ( mGameKeyStates.rightDirectKey == KEYSTATE_PRESSED ) moveInfo |= 2;
			if ( mGameKeyStates.upDirectKey == KEYSTATE_PRESSED	)	moveInfo |= 1;
			if ( mGameKeyStates.downDirectKey == KEYSTATE_PRESSED )	moveInfo |= 8;

			//  ϴ  map ̵  ̴?
			Point willGoPosition = GetPosition();
			if ( mGameKeyStates.leftDirectKey ==  KEYSTATE_PRESSED )willGoPosition = willGoPosition + Point( -1.f, 0.f ) * (mRadius + dTime * 100.f);
			if ( mGameKeyStates.rightDirectKey == KEYSTATE_PRESSED )willGoPosition = willGoPosition + Point( +1.f, 0.f ) * (mRadius + dTime * 100.f);
			if ( mGameKeyStates.upDirectKey == KEYSTATE_PRESSED )	willGoPosition = willGoPosition + Point( 0.f, -1.f ) * (mRadius + dTime * 100.f);
			if ( mGameKeyStates.downDirectKey == KEYSTATE_PRESSED )	willGoPosition = willGoPosition + Point( 0.f, 1.f ) * (mRadius + dTime * 100.f);

			//wasd    Ȯ
			if ( mGameKeyStates.leftDirectKey ==  KEYSTATE_NOTPRESSED
				&& mGameKeyStates.rightDirectKey == KEYSTATE_NOTPRESSED
				&& mGameKeyStates.upDirectKey == KEYSTATE_NOTPRESSED
				&& mGameKeyStates.downDirectKey == KEYSTATE_NOTPRESSED )
			{
				TransState(PLAYER_STATE_IDLE);
				break;
			}

			if ( GGameMap->isValidTile(willGoPosition) == false )
			{
				//ϱ Idle· .
				TransState(PLAYER_STATE_IDLE);
				break;
			}
			//׸   ʴ , Ʒ SetPosition ̵ϰ ͸  Ǹ Ŭ 忡  ó ...
			SetPosition(willGoPosition);

			// ٸ  ̵ߴ?
			if( mMovedInfo != -1 && moveInfo != mMovedInfo)
			{
				//ٲ key .
				GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
				outPacket.mMyPlayerInfo = this->GetPlayerInfo();
				mClient->Broadcast(&outPacket);
			}

			mMovedInfo = moveInfo;

		}
		break;
	case PLAYER_STATE_ATTACK:
		{
			Point AttackPoint = mPosition + Point(cos(mRotation) * mAttackRange,sin(mRotation) * mAttackRange);
			std::map<int,Player*> players = GPlayerManager->GetPlayers();
			for( std::map<int,Player*>::iterator it = players.begin(); it != players.end(); ++it )
			{
				Player* enemy = it->second;
				if(enemy == this)continue;

				if( Point().GetDistance( enemy->GetPosition(), AttackPoint ) < mAttackRange )
				{
					//ǰݵ
					enemy->Damaged(mHP);
				}
			}
			TransState(PLAYER_STATE_IDLE);
			break;
		}
		break;

	case PLAYER_STATE_DIE:
		{
			mResponTime -= dTime;
			if(mResponTime < 0)
			{
				//մϴ.
				while(1)
				{
					float x = rand() % (GGameMap->GetWidth() * 64);
					float y = rand() % (GGameMap->GetHeight() * 64);
					if(GGameMap->isValidTile(Point(x,y)) == true)
					{
						mPosition = Point(x,y);
						break;
					}
				}
				SetHP(100);
				TransState(PLAYER_STATE_IDLE);
				break;
			}
		}
		break;
	case PLAYER_STATE_TYPESKILL:
		{
			TransState(PLAYER_STATE_IDLE);
			break;
		}
		break;
	case PLAYER_STATE_USERSKILL:
		{
			TransState(PLAYER_STATE_IDLE);
			break;
		}
		break;
	default:
		break;
	}
}
void Player::Damaged(int damage)
{
	if(mHP < damage)
	{
		//׾
		TransState(PLAYER_STATE_DIE);
	}
	else
	{
		mHP-=damage;
		//  󸶶 εĳ
		HPUpdateResult outPacket = HPUpdateResult();
		outPacket.mPlayerId = mPlayerId;
		outPacket.mHP = mHP;
		mClient->Broadcast(&outPacket);
	}

}
PlayerInfo Player::GetPlayerInfo()
{
	PlayerInfo mPlayerInfo;
	mPlayerInfo.mGameKeyStates = mGameKeyStates;
	mPlayerInfo.mX = mPosition.x;
	mPlayerInfo.mY = mPosition.y;
	mPlayerInfo.mPlayerId = mPlayerId;
	mPlayerInfo.mAngle = mRotation;
	mPlayerInfo.mPlayerState = mPlayerState;
	mPlayerInfo.mHP = mHP;
	return mPlayerInfo;
}<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 Francois Beaune, Jupiter Jazz Limited
//
// 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.
//

// Interface header.
#include "genericsamplegenerator.h"

// appleseed.renderer headers.
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/rendering/isamplerenderer.h"
#include "renderer/kernel/rendering/localaccumulationframebuffer.h"
#include "renderer/kernel/rendering/sample.h"
#include "renderer/kernel/rendering/samplegeneratorbase.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/modeling/frame/frame.h"

// appleseed.foundation headers.
#include "foundation/image/canvasproperties.h"
#include "foundation/image/image.h"
#include "foundation/math/population.h"
#include "foundation/math/qmc.h"
#include "foundation/math/rng.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/statistics.h"

// Standard headers.
#include <cassert>
#include <vector>

// Forward declarations.
namespace foundation    { class LightingConditions; }

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    class GenericSampleGenerator
      : public SampleGeneratorBase
    {
      public:
        GenericSampleGenerator(
            const Frame&                    frame,
            ISampleRendererFactory*         sample_renderer_factory,
            const size_t                    generator_index,
            const size_t                    generator_count)
          : SampleGeneratorBase(generator_index, generator_count)
          , m_frame(frame)
          , m_frame_props(frame.image().properties())
          , m_lighting_conditions(frame.get_lighting_conditions())
          , m_sample_renderer(sample_renderer_factory->create())
          , m_frame_width_next_pow2(next_power(static_cast<double>(m_frame_props.m_canvas_width), 2.0))
          , m_frame_height_next_pow3(next_power(static_cast<double>(m_frame_props.m_canvas_height), 3.0))
        {
        }

        virtual void release() override
        {
            delete this;
        }

        virtual void reset() override
        {
            SampleGeneratorBase::reset();
            m_rng = MersenneTwister();
        }

        virtual StatisticsVector get_statistics() const override
        {
            Statistics stats;
            stats.insert("max. samp. dim.", m_total_sampling_dim);
            stats.insert("max. samp. inst.", m_total_sampling_inst);

            StatisticsVector vec;
            vec.insert("generic sample generator statistics", stats);
            vec.merge(m_sample_renderer->get_statistics());

            return vec;
        }

      private:
        const Frame&                        m_frame;
        const CanvasProperties&             m_frame_props;
        const LightingConditions&           m_lighting_conditions;
        auto_release_ptr<ISampleRenderer>   m_sample_renderer;
        MersenneTwister                     m_rng;

        const double                        m_frame_width_next_pow2;
        const double                        m_frame_height_next_pow3;

        Population<size_t>                  m_total_sampling_dim;
        Population<size_t>                  m_total_sampling_inst;

        virtual size_t generate_samples(
            const size_t                    sequence_index,
            SampleVector&                   samples) override
        {
            // Compute the sample position in NDC.
            const size_t Bases[2] = { 2, 3 };
            const Vector2d s = halton_sequence<double, 2>(Bases, sequence_index);

            // Compute the coordinates of the pixel in the larger frame.
            const Vector2d t(s[0] * m_frame_width_next_pow2, s[1] * m_frame_height_next_pow3);
            const size_t x = truncate<size_t>(t[0]);
            const size_t y = truncate<size_t>(t[1]);

            // Reject samples that fall outside the actual frame.
            if (x >= m_frame_props.m_canvas_width || y >= m_frame_props.m_canvas_height)
                return 0;

            // Transform the sample position back to NDC. Full precision divisions are required
            // to ensure that the sample position indeed lies in the [0,1)^2 interval.
            const Vector2d sample_position(
                t[0] / m_frame_props.m_canvas_width,
                t[1] / m_frame_props.m_canvas_height);

            // Create a sampling context. We start with an initial dimension of 2,
            // corresponding to the Halton sequence used for the sample positions.
            SamplingContext sampling_context(
                m_rng,
                2,                          // number of dimensions
                sequence_index,             // number of samples
                sequence_index);            // initial instance number

            // Render the sample.
            ShadingResult shading_result;
            m_sample_renderer->render_sample(
                sampling_context,
                sample_position,
                shading_result);

            // Transform the sample to the linear RGB color space.
            shading_result.transform_to_linear_rgb(m_lighting_conditions);

            // Create a single sample.
            Sample sample;
            sample.m_position = sample_position;
            sample.m_color[0] = shading_result.m_color[0];
            sample.m_color[1] = shading_result.m_color[1];
            sample.m_color[2] = shading_result.m_color[2];
            sample.m_color[3] = shading_result.m_alpha[0];
            samples.push_back(sample);

            m_total_sampling_dim.insert(sampling_context.get_total_dimension());
            m_total_sampling_inst.insert(sampling_context.get_total_instance());

            return 1;
        }
    };
}

//
// GenericSampleGeneratorFactory class implementation.
//

GenericSampleGeneratorFactory::GenericSampleGeneratorFactory(
    const Frame&            frame,
    ISampleRendererFactory* sample_renderer_factory)
  : m_frame(frame)
  , m_sample_renderer_factory(sample_renderer_factory)
{
}

void GenericSampleGeneratorFactory::release()
{
    delete this;
}

ISampleGenerator* GenericSampleGeneratorFactory::create(
    const size_t            generator_index,
    const size_t            generator_count)
{
    return
        new GenericSampleGenerator(
            m_frame,
            m_sample_renderer_factory,
            generator_index,
            generator_count);
}

AccumulationFramebuffer* GenericSampleGeneratorFactory::create_accumulation_framebuffer(
    const size_t            canvas_width,
    const size_t            canvas_height)
{
    return
        new LocalAccumulationFramebuffer(
            canvas_width,
            canvas_height);
}

}   // namespace renderer
<commit_msg>changed some statistics to use 64-bit unsigned integers.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 Francois Beaune, Jupiter Jazz Limited
//
// 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.
//

// Interface header.
#include "genericsamplegenerator.h"

// appleseed.renderer headers.
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/rendering/isamplerenderer.h"
#include "renderer/kernel/rendering/localaccumulationframebuffer.h"
#include "renderer/kernel/rendering/sample.h"
#include "renderer/kernel/rendering/samplegeneratorbase.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/modeling/frame/frame.h"

// appleseed.foundation headers.
#include "foundation/image/canvasproperties.h"
#include "foundation/image/image.h"
#include "foundation/math/population.h"
#include "foundation/math/qmc.h"
#include "foundation/math/rng.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"
#include "foundation/platform/types.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/statistics.h"

// Standard headers.
#include <cassert>
#include <vector>

// Forward declarations.
namespace foundation    { class LightingConditions; }

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    class GenericSampleGenerator
      : public SampleGeneratorBase
    {
      public:
        GenericSampleGenerator(
            const Frame&                    frame,
            ISampleRendererFactory*         sample_renderer_factory,
            const size_t                    generator_index,
            const size_t                    generator_count)
          : SampleGeneratorBase(generator_index, generator_count)
          , m_frame(frame)
          , m_frame_props(frame.image().properties())
          , m_lighting_conditions(frame.get_lighting_conditions())
          , m_sample_renderer(sample_renderer_factory->create())
          , m_frame_width_next_pow2(next_power(static_cast<double>(m_frame_props.m_canvas_width), 2.0))
          , m_frame_height_next_pow3(next_power(static_cast<double>(m_frame_props.m_canvas_height), 3.0))
        {
        }

        virtual void release() override
        {
            delete this;
        }

        virtual void reset() override
        {
            SampleGeneratorBase::reset();
            m_rng = MersenneTwister();
        }

        virtual StatisticsVector get_statistics() const override
        {
            Statistics stats;
            stats.insert("max. samp. dim.", m_total_sampling_dim);
            stats.insert("max. samp. inst.", m_total_sampling_inst);

            StatisticsVector vec;
            vec.insert("generic sample generator statistics", stats);
            vec.merge(m_sample_renderer->get_statistics());

            return vec;
        }

      private:
        const Frame&                        m_frame;
        const CanvasProperties&             m_frame_props;
        const LightingConditions&           m_lighting_conditions;
        auto_release_ptr<ISampleRenderer>   m_sample_renderer;
        MersenneTwister                     m_rng;

        const double                        m_frame_width_next_pow2;
        const double                        m_frame_height_next_pow3;

        Population<uint64>                  m_total_sampling_dim;
        Population<uint64>                  m_total_sampling_inst;

        virtual size_t generate_samples(
            const size_t                    sequence_index,
            SampleVector&                   samples) override
        {
            // Compute the sample position in NDC.
            const size_t Bases[2] = { 2, 3 };
            const Vector2d s = halton_sequence<double, 2>(Bases, sequence_index);

            // Compute the coordinates of the pixel in the larger frame.
            const Vector2d t(s[0] * m_frame_width_next_pow2, s[1] * m_frame_height_next_pow3);
            const size_t x = truncate<size_t>(t[0]);
            const size_t y = truncate<size_t>(t[1]);

            // Reject samples that fall outside the actual frame.
            if (x >= m_frame_props.m_canvas_width || y >= m_frame_props.m_canvas_height)
                return 0;

            // Transform the sample position back to NDC. Full precision divisions are required
            // to ensure that the sample position indeed lies in the [0,1)^2 interval.
            const Vector2d sample_position(
                t[0] / m_frame_props.m_canvas_width,
                t[1] / m_frame_props.m_canvas_height);

            // Create a sampling context. We start with an initial dimension of 2,
            // corresponding to the Halton sequence used for the sample positions.
            SamplingContext sampling_context(
                m_rng,
                2,                          // number of dimensions
                sequence_index,             // number of samples
                sequence_index);            // initial instance number

            // Render the sample.
            ShadingResult shading_result;
            m_sample_renderer->render_sample(
                sampling_context,
                sample_position,
                shading_result);

            // Transform the sample to the linear RGB color space.
            shading_result.transform_to_linear_rgb(m_lighting_conditions);

            // Create a single sample.
            Sample sample;
            sample.m_position = sample_position;
            sample.m_color[0] = shading_result.m_color[0];
            sample.m_color[1] = shading_result.m_color[1];
            sample.m_color[2] = shading_result.m_color[2];
            sample.m_color[3] = shading_result.m_alpha[0];
            samples.push_back(sample);

            m_total_sampling_dim.insert(sampling_context.get_total_dimension());
            m_total_sampling_inst.insert(sampling_context.get_total_instance());

            return 1;
        }
    };
}

//
// GenericSampleGeneratorFactory class implementation.
//

GenericSampleGeneratorFactory::GenericSampleGeneratorFactory(
    const Frame&            frame,
    ISampleRendererFactory* sample_renderer_factory)
  : m_frame(frame)
  , m_sample_renderer_factory(sample_renderer_factory)
{
}

void GenericSampleGeneratorFactory::release()
{
    delete this;
}

ISampleGenerator* GenericSampleGeneratorFactory::create(
    const size_t            generator_index,
    const size_t            generator_count)
{
    return
        new GenericSampleGenerator(
            m_frame,
            m_sample_renderer_factory,
            generator_index,
            generator_count);
}

AccumulationFramebuffer* GenericSampleGeneratorFactory::create_accumulation_framebuffer(
    const size_t            canvas_width,
    const size_t            canvas_height)
{
    return
        new LocalAccumulationFramebuffer(
            canvas_width,
            canvas_height);
}

}   // namespace renderer
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DrawViewWrapper.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-25 08:39:24 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _CHART2_DRAW_VIEW_WRAPPER_HXX
#define _CHART2_DRAW_VIEW_WRAPPER_HXX

#ifndef _E3D_VIEW3D_HXX
#include <svx/view3d.hxx>
#endif

#ifndef _COM_SUN_STAR_DRAWING_XSHAPE_HPP_
#include <com/sun/star/drawing/XShape.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XMODEL_HPP_
#include <com/sun/star/frame/XModel.hpp>
#endif

class SdrModel;

//.............................................................................
namespace chart
{
//.............................................................................

//-----------------------------------------------------------------------------
/** The DrawViewWrapper should help us to reduce effort if the underlying DrawingLayer changes.
Another task is to hide functionality we do not need, for example more than one page.
*/

class MarkHandleProvider
{
public:
    virtual bool getMarkHandles( SdrHdlList& rHdlList ) =0;
    virtual bool getFrameDragSingles() =0;
};

class DrawViewWrapper : public E3dView
{
public:
    DrawViewWrapper(SdrModel* pModel, OutputDevice* pOut);
    virtual ~DrawViewWrapper();

    //triggers the use of an updated first page
    void    ReInit();

    /// tries to get an OutputDevice from the XParent of the model to use as reference device
    void attachParentReferenceDevice(
        const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > & xChartModel );

    //fill list of selection handles 'aHdl'
    virtual void SetMarkHandles();

    SdrPageView*    GetPageView() const;

    SdrObject* getHitObject( const Point& rPnt ) const;
    //BOOL PickObj(const Point& rPnt, short nTol, SdrObject*& rpObj, SdrPageView*& rpPV, ULONG nOptions, SdrObject** ppRootObj, ULONG* pnMarkNum=NULL, USHORT* pnPassNum=NULL) const;
    //BOOL PickObj(const Point& rPnt, short nTol, SdrObject*& rpObj, SdrPageView*& rpPV, ULONG nOptions=0) const;
    //BOOL PickObj(const Point& rPnt, SdrObject*& rpObj, SdrPageView*& rpPV, ULONG nOptions=0) const { return PickObj(rPnt,nHitTolLog,rpObj,rpPV,nOptions); }

    //void MarkObj(SdrObject* pObj, SdrPageView* pPV, BOOL bUnmark=FALSE, BOOL bImpNoSetMarkHdl=FALSE);
    void MarkObject( SdrObject* pObj );

    //----------------------
    //pMarkHandleProvider can be NULL; ownership is not taken
    void setMarkHandleProvider( MarkHandleProvider* pMarkHandleProvider );
    void CompleteRedraw( OutputDevice* pOut, const Region& rReg, USHORT nPaintMode = 0,
                         ::sdr::contact::ViewObjectContactRedirector* pRedirector = 0L );

    SdrObject*   getSelectedObject() const;
    SdrObject*   getTextEditObject() const;
    SdrOutliner* getOutliner() const;

    SfxItemSet   getPositionAndSizeItemSetFromMarkedObject() const;

    SdrObject* getNamedSdrObject( const rtl::OUString& rName ) const;
    bool IsObjectHit( SdrObject* pObj, const Point& rPnt ) const;

    virtual void SFX_NOTIFY(SfxBroadcaster& rBC, const TypeId& rBCType, const SfxHint& rHint, const TypeId& rHintType);

    static SdrObject* getSdrObject( const ::com::sun::star::uno::Reference<
                    ::com::sun::star::drawing::XShape >& xShape );

private:
    mutable MarkHandleProvider*     m_pMarkHandleProvider;

    ::std::auto_ptr< SdrOutliner >  m_apOutliner;
};

//.............................................................................
} //namespace chart
//.............................................................................
#endif

<commit_msg>INTEGRATION: CWS chart15 (1.9.22); FILE MERGED 2007/12/05 12:21:19 bm 1.9.22.2: #i79965# scroll window back after text edit 2007/11/29 17:36:50 iha 1.9.22.1: #i82893#,#i75867# charts must be painted resolution dependent<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DrawViewWrapper.hxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: ihi $ $Date: 2008-01-14 13:57:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _CHART2_DRAW_VIEW_WRAPPER_HXX
#define _CHART2_DRAW_VIEW_WRAPPER_HXX

#ifndef _E3D_VIEW3D_HXX
#include <svx/view3d.hxx>
#endif

#ifndef _COM_SUN_STAR_DRAWING_XSHAPE_HPP_
#include <com/sun/star/drawing/XShape.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XMODEL_HPP_
#include <com/sun/star/frame/XModel.hpp>
#endif

class SdrModel;

//.............................................................................
namespace chart
{
//.............................................................................

//-----------------------------------------------------------------------------
/** The DrawViewWrapper should help us to reduce effort if the underlying DrawingLayer changes.
Another task is to hide functionality we do not need, for example more than one page.
*/

class MarkHandleProvider
{
public:
    virtual bool getMarkHandles( SdrHdlList& rHdlList ) =0;
    virtual bool getFrameDragSingles() =0;
};

class DrawViewWrapper : public E3dView
{
public:
    DrawViewWrapper(SdrModel* pModel, OutputDevice* pOut, bool bPaintPageForEditMode);
    virtual ~DrawViewWrapper();

    //triggers the use of an updated first page
    void    ReInit();

    /// tries to get an OutputDevice from the XParent of the model to use as reference device
    void attachParentReferenceDevice(
        const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > & xChartModel );

    //fill list of selection handles 'aHdl'
    virtual void SetMarkHandles();

    SdrPageView*    GetPageView() const;

    SdrObject* getHitObject( const Point& rPnt ) const;
    //BOOL PickObj(const Point& rPnt, short nTol, SdrObject*& rpObj, SdrPageView*& rpPV, ULONG nOptions, SdrObject** ppRootObj, ULONG* pnMarkNum=NULL, USHORT* pnPassNum=NULL) const;
    //BOOL PickObj(const Point& rPnt, short nTol, SdrObject*& rpObj, SdrPageView*& rpPV, ULONG nOptions=0) const;
    //BOOL PickObj(const Point& rPnt, SdrObject*& rpObj, SdrPageView*& rpPV, ULONG nOptions=0) const { return PickObj(rPnt,nHitTolLog,rpObj,rpPV,nOptions); }

    //void MarkObj(SdrObject* pObj, SdrPageView* pPV, BOOL bUnmark=FALSE, BOOL bImpNoSetMarkHdl=FALSE);
    void MarkObject( SdrObject* pObj );

    //----------------------
    //pMarkHandleProvider can be NULL; ownership is not taken
    void setMarkHandleProvider( MarkHandleProvider* pMarkHandleProvider );
    void CompleteRedraw( OutputDevice* pOut, const Region& rReg, USHORT nPaintMode = 0,
                         ::sdr::contact::ViewObjectContactRedirector* pRedirector = 0L );

    SdrObject*   getSelectedObject() const;
    SdrObject*   getTextEditObject() const;
    SdrOutliner* getOutliner() const;

    SfxItemSet   getPositionAndSizeItemSetFromMarkedObject() const;

    SdrObject* getNamedSdrObject( const rtl::OUString& rName ) const;
    bool IsObjectHit( SdrObject* pObj, const Point& rPnt ) const;

    virtual void SFX_NOTIFY(SfxBroadcaster& rBC, const TypeId& rBCType, const SfxHint& rHint, const TypeId& rHintType);

    static SdrObject* getSdrObject( const ::com::sun::star::uno::Reference<
                    ::com::sun::star::drawing::XShape >& xShape );

private:
    mutable MarkHandleProvider*     m_pMarkHandleProvider;

    ::std::auto_ptr< SdrOutliner >  m_apOutliner;

    // #i79965# scroll back view when ending text edit
    bool m_bRestoreMapMode;
    MapMode m_aMapModeToRestore;
};

//.............................................................................
} //namespace chart
//.............................................................................
#endif

<|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/.
 */

#include "macros.hxx"
#include "PropertyMapper.hxx"
#include "CommonConverters.hxx"

#include "AbstractShapeFactory.hxx"
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/drawing/CircleKind.hpp>
#include <com/sun/star/drawing/DoubleSequence.hpp>
#include <com/sun/star/drawing/FlagSequence.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/drawing/NormalsKind.hpp>
#include <com/sun/star/drawing/PointSequence.hpp>
#include <com/sun/star/drawing/PolygonKind.hpp>
#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
#include <com/sun/star/drawing/ProjectionMode.hpp>
#include <com/sun/star/drawing/ShadeMode.hpp>
#include <com/sun/star/drawing/TextFitToSizeType.hpp>
#include <com/sun/star/drawing/TextureProjectionMode.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/uno/Any.hxx>

#include <editeng/unoprnms.hxx>
#include <rtl/math.hxx>
#include <svx/svdocirc.hxx>
#include <svx/svdopath.hxx>
#include <vcl/svapp.hxx>

#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b3dhommatrix.hxx>

#include <osl/module.hxx>

#include "OpenglShapeFactory.hxx"
#include "ShapeFactory.hxx"

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

namespace chart {

namespace {

typedef opengl::OpenglShapeFactory* (*__getOpenglShapeFactory)(void);

static void SAL_CALL thisModule() {}

osl::Module* getOpenGLModule()
{
    static osl::Module aModule;
    if (aModule.is())
        // Already loaded.
        return &aModule;

    OUString aLibName(SVLIBRARY("chartopengl"));
    bool bLoaded = aModule.loadRelative(&thisModule, aLibName);
    if (!bLoaded)
        bLoaded = aModule.load(aLibName);

    return bLoaded ? &aModule : NULL;
}

}

AbstractShapeFactory* AbstractShapeFactory::getOrCreateShapeFactory(uno::Reference< lang::XMultiServiceFactory> xFactory)
{
    static AbstractShapeFactory* pShapeFactory = NULL;

    if(pShapeFactory)
        return pShapeFactory;

    if(getenv("CHART_DUMMY_FACTORY") && !Application::IsHeadlessModeEnabled())
    {
        osl::Module* pModule = getOpenGLModule();
        if(pModule)
        {
            oslGenericFunction fn = pModule->getFunctionSymbol("getOpenglShapeFactory");
            if(fn)
            {

                pShapeFactory = reinterpret_cast<__getOpenglShapeFactory>(fn)();
                pShapeFactory->setShapeFactory(xFactory);
            }
        }
    }

    if(!pShapeFactory)
        pShapeFactory = new ShapeFactory(xFactory);

    return pShapeFactory;
}

sal_Int32 AbstractShapeFactory::getSymbolCount()
{
    return Symbol_COUNT;
}

uno::Reference< drawing::XShapes > AbstractShapeFactory::getChartRootShape(
    const uno::Reference< drawing::XDrawPage>& xDrawPage )
{
    uno::Reference< drawing::XShapes > xRet;
    uno::Reference< drawing::XShapes > xShapes( xDrawPage, uno::UNO_QUERY );
    if( xShapes.is() )
    {
        sal_Int32 nCount = xShapes->getCount();
        uno::Reference< drawing::XShape > xShape;
        for( sal_Int32 nN = nCount; nN--; )
        {
            if( xShapes->getByIndex( nN ) >>= xShape )
            {
                if( AbstractShapeFactory::getShapeName( xShape ).equals("com.sun.star.chart2.shapes") )
                {
                    xRet = uno::Reference< drawing::XShapes >( xShape, uno::UNO_QUERY );
                    break;
                }
            }
        }
    }
    return xRet;
}

void AbstractShapeFactory::makeShapeInvisible( const uno::Reference< drawing::XShape >& xShape )
{
    uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
    OSL_ENSURE(xShapeProp.is(), "created shape offers no XPropertySet");
    if( xShapeProp.is())
    {
        try
        {
            xShapeProp->setPropertyValue( "LineStyle", uno::makeAny( drawing::LineStyle_NONE ));
            xShapeProp->setPropertyValue( "FillStyle", uno::makeAny( drawing::FillStyle_NONE ));
        }
        catch( const uno::Exception& e )
        {
            ASSERT_EXCEPTION( e );
        }
    }
}

// set a name/CID at a shape (is used for selection handling)

void AbstractShapeFactory::setShapeName( const uno::Reference< drawing::XShape >& xShape
                               , const OUString& rName )
{
    if(!xShape.is())
        return;
    uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
    OSL_ENSURE(xProp.is(), "shape offers no XPropertySet");
    if( xProp.is())
    {
        try
        {
            xProp->setPropertyValue( UNO_NAME_MISC_OBJ_NAME
                , uno::makeAny( rName ) );
        }
        catch( const uno::Exception& e )
        {
            ASSERT_EXCEPTION( e );
        }
    }
}

OUString AbstractShapeFactory::getShapeName( const uno::Reference< drawing::XShape >& xShape )
{
    OUString aRet;

    uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
    OSL_ENSURE(xProp.is(), "shape offers no XPropertySet");
    if( xProp.is())
    {
        try
        {
            xProp->getPropertyValue( UNO_NAME_MISC_OBJ_NAME ) >>= aRet;
        }
        catch( const uno::Exception& e )
        {
            ASSERT_EXCEPTION( e );
        }
    }

    return aRet;
}

uno::Any AbstractShapeFactory::makeTransformation( const awt::Point& rScreenPosition2D, double fRotationAnglePi )
{
    ::basegfx::B2DHomMatrix aM;
    //As autogrow is active the rectangle is automatically expanded to that side
    //to which the text is not adjusted.
    // aM.scale( 1, 1 ); Oops? A scale with this parameters is neutral, line commented out
    aM.rotate( fRotationAnglePi );
    aM.translate( rScreenPosition2D.X, rScreenPosition2D.Y );
    uno::Any aATransformation = uno::makeAny( B2DHomMatrixToHomogenMatrix3(aM) );
    return aATransformation;
}

OUString AbstractShapeFactory::getStackedString( const OUString& rString, bool bStacked )
{
    sal_Int32 nLen = rString.getLength();
    if(!bStacked || !nLen)
        return rString;

    OUStringBuffer aStackStr;

    //add a newline after each letter
    //as we do not no letters here add a newline after each char
    for( sal_Int32 nPosSrc=0; nPosSrc < nLen; nPosSrc++ )
    {
        if( nPosSrc )
            aStackStr.append( '\r' );
        aStackStr.append(rString[nPosSrc]);
    }
    return aStackStr.makeStringAndClear();
}

bool AbstractShapeFactory::hasPolygonAnyLines( drawing::PolyPolygonShape3D& rPoly)
{
    // #i67757# check all contained polygons, if at least one polygon contains 2 or more points, return true
    for( sal_Int32 nIdx = 0, nCount = rPoly.SequenceX.getLength(); nIdx < nCount; ++nIdx )
        if( rPoly.SequenceX[ nIdx ].getLength() > 1 )
            return true;
    return false;
}

bool AbstractShapeFactory::isPolygonEmptyOrSinglePoint( drawing::PolyPolygonShape3D& rPoly)
{
    // true, if empty polypolygon or one polygon with one point
    return (rPoly.SequenceX.getLength() == 0) ||
        ((rPoly.SequenceX.getLength() == 1) && (rPoly.SequenceX[0].getLength() <= 1));
}

void AbstractShapeFactory::closePolygon( drawing::PolyPolygonShape3D& rPoly)
{
    OSL_ENSURE( rPoly.SequenceX.getLength() <= 1, "AbstractShapeFactory::closePolygon - single polygon expected" );
    //add a last point == first point
    if(isPolygonEmptyOrSinglePoint(rPoly))
        return;
    drawing::Position3D aFirst(rPoly.SequenceX[0][0],rPoly.SequenceY[0][0],rPoly.SequenceZ[0][0]);
    AddPointToPoly( rPoly, aFirst );
}

awt::Size AbstractShapeFactory::calculateNewSizeRespectingAspectRatio(
         const awt::Size& rTargetSize
         , const awt::Size& rSourceSizeWithCorrectAspectRatio )
{
    awt::Size aNewSize;

    double fFactorWidth = double(rTargetSize.Width)/double(rSourceSizeWithCorrectAspectRatio.Width);
    double fFactorHeight = double(rTargetSize.Height)/double(rSourceSizeWithCorrectAspectRatio.Height);
    double fFactor = std::min(fFactorWidth,fFactorHeight);
    aNewSize.Width=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Width);
    aNewSize.Height=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Height);

    return aNewSize;
}

awt::Point AbstractShapeFactory::calculateTopLeftPositionToCenterObject(
           const awt::Point& rTargetAreaPosition
         , const awt::Size& rTargetAreaSize
         , const awt::Size& rObjectSize )
{
    awt::Point aNewPosition(rTargetAreaPosition);
    aNewPosition.X += static_cast<sal_Int32>(double(rTargetAreaSize.Width-rObjectSize.Width)/2.0);
    aNewPosition.Y += static_cast<sal_Int32>(double(rTargetAreaSize.Height-rObjectSize.Height)/2.0);
    return aNewPosition;
}

::basegfx::B2IRectangle AbstractShapeFactory::getRectangleOfShape(
        const uno::Reference< drawing::XShape >& xShape )
{
    ::basegfx::B2IRectangle aRet;

    if( xShape.is() )
    {
        awt::Point aPos = xShape->getPosition();
        awt::Size aSize = xShape->getSize();
        aRet = BaseGFXHelper::makeRectangle(aPos,aSize);
    }
    return aRet;

}

awt::Size AbstractShapeFactory::getSizeAfterRotation(
         const uno::Reference< drawing::XShape >& xShape, double fRotationAngleDegree )
{
    awt::Size aRet(0,0);
    if(xShape.is())
    {
        const awt::Size aSize( xShape->getSize() );

        if( ::rtl::math::approxEqual( fRotationAngleDegree, 0.0 ) )
            aRet = aSize;
        else
        {
            while(fRotationAngleDegree>=360.0)
                fRotationAngleDegree-=360.0;
            while(fRotationAngleDegree<0.0)
                fRotationAngleDegree+=360.0;
            if(fRotationAngleDegree>270.0)
                fRotationAngleDegree=360.0-fRotationAngleDegree;
            else if(fRotationAngleDegree>180.0)
                fRotationAngleDegree=fRotationAngleDegree-180.0;
            else if(fRotationAngleDegree>90.0)
                fRotationAngleDegree=180.0-fRotationAngleDegree;

            const double fAnglePi = fRotationAngleDegree*F_PI/180.0;

            aRet.Height = static_cast<sal_Int32>(
                aSize.Width*rtl::math::sin( fAnglePi )
                + aSize.Height*rtl::math::cos( fAnglePi ));
            aRet.Width = static_cast<sal_Int32>(
                aSize.Width*rtl::math::cos( fAnglePi )
                + aSize.Height*rtl::math::sin( fAnglePi ));
        }
    }
    return aRet;
}

void AbstractShapeFactory::removeSubShapes( const uno::Reference< drawing::XShapes >& xShapes )
{
    if( xShapes.is() )
    {
        sal_Int32 nSubCount = xShapes->getCount();
        uno::Reference< drawing::XShape > xShape;
        for( sal_Int32 nS = nSubCount; nS--; )
        {
            if( xShapes->getByIndex( nS ) >>= xShape )
                xShapes->remove( xShape );
        }
    }
}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Adapt for the DISABLE_DYNLOADING case<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/.
 */

#include "macros.hxx"
#include "PropertyMapper.hxx"
#include "CommonConverters.hxx"

#include "AbstractShapeFactory.hxx"
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/drawing/CircleKind.hpp>
#include <com/sun/star/drawing/DoubleSequence.hpp>
#include <com/sun/star/drawing/FlagSequence.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/drawing/NormalsKind.hpp>
#include <com/sun/star/drawing/PointSequence.hpp>
#include <com/sun/star/drawing/PolygonKind.hpp>
#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
#include <com/sun/star/drawing/ProjectionMode.hpp>
#include <com/sun/star/drawing/ShadeMode.hpp>
#include <com/sun/star/drawing/TextFitToSizeType.hpp>
#include <com/sun/star/drawing/TextureProjectionMode.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/uno/Any.hxx>

#include <editeng/unoprnms.hxx>
#include <rtl/math.hxx>
#include <svx/svdocirc.hxx>
#include <svx/svdopath.hxx>
#include <vcl/svapp.hxx>

#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b3dhommatrix.hxx>

#include <osl/module.hxx>

#include "OpenglShapeFactory.hxx"
#include "ShapeFactory.hxx"

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

namespace chart {

namespace {

typedef opengl::OpenglShapeFactory* (*__getOpenglShapeFactory)(void);

#ifndef DISABLE_DYNLOADING

static void SAL_CALL thisModule() {}

osl::Module* getOpenGLModule()
{
    static osl::Module aModule;
    if (aModule.is())
        // Already loaded.
        return &aModule;

    OUString aLibName(SVLIBRARY("chartopengl"));
    bool bLoaded = aModule.loadRelative(&thisModule, aLibName);
    if (!bLoaded)
        bLoaded = aModule.load(aLibName);

    return bLoaded ? &aModule : NULL;
}

#endif

}

#ifdef DISABLE_DYNLOADING
extern "C" opengl::OpenglShapeFactory* getOpenglShapeFactory();
#endif

AbstractShapeFactory* AbstractShapeFactory::getOrCreateShapeFactory(uno::Reference< lang::XMultiServiceFactory> xFactory)
{
    static AbstractShapeFactory* pShapeFactory = NULL;

    if(pShapeFactory)
        return pShapeFactory;

    if(getenv("CHART_DUMMY_FACTORY") && !Application::IsHeadlessModeEnabled())
    {
#ifndef DISABLE_DYNLOADING
        osl::Module* pModule = getOpenGLModule();
        if(pModule)
        {
            oslGenericFunction fn = pModule->getFunctionSymbol("getOpenglShapeFactory");
            if(fn)
            {

                pShapeFactory = reinterpret_cast<__getOpenglShapeFactory>(fn)();
                pShapeFactory->setShapeFactory(xFactory);
            }
        }
#else
        pShapeFactory = getOpenglShapeFactory();
        pShapeFactory->setShapeFactory(xFactory);
#endif
    }

    if(!pShapeFactory)
        pShapeFactory = new ShapeFactory(xFactory);

    return pShapeFactory;
}

sal_Int32 AbstractShapeFactory::getSymbolCount()
{
    return Symbol_COUNT;
}

uno::Reference< drawing::XShapes > AbstractShapeFactory::getChartRootShape(
    const uno::Reference< drawing::XDrawPage>& xDrawPage )
{
    uno::Reference< drawing::XShapes > xRet;
    uno::Reference< drawing::XShapes > xShapes( xDrawPage, uno::UNO_QUERY );
    if( xShapes.is() )
    {
        sal_Int32 nCount = xShapes->getCount();
        uno::Reference< drawing::XShape > xShape;
        for( sal_Int32 nN = nCount; nN--; )
        {
            if( xShapes->getByIndex( nN ) >>= xShape )
            {
                if( AbstractShapeFactory::getShapeName( xShape ).equals("com.sun.star.chart2.shapes") )
                {
                    xRet = uno::Reference< drawing::XShapes >( xShape, uno::UNO_QUERY );
                    break;
                }
            }
        }
    }
    return xRet;
}

void AbstractShapeFactory::makeShapeInvisible( const uno::Reference< drawing::XShape >& xShape )
{
    uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
    OSL_ENSURE(xShapeProp.is(), "created shape offers no XPropertySet");
    if( xShapeProp.is())
    {
        try
        {
            xShapeProp->setPropertyValue( "LineStyle", uno::makeAny( drawing::LineStyle_NONE ));
            xShapeProp->setPropertyValue( "FillStyle", uno::makeAny( drawing::FillStyle_NONE ));
        }
        catch( const uno::Exception& e )
        {
            ASSERT_EXCEPTION( e );
        }
    }
}

// set a name/CID at a shape (is used for selection handling)

void AbstractShapeFactory::setShapeName( const uno::Reference< drawing::XShape >& xShape
                               , const OUString& rName )
{
    if(!xShape.is())
        return;
    uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
    OSL_ENSURE(xProp.is(), "shape offers no XPropertySet");
    if( xProp.is())
    {
        try
        {
            xProp->setPropertyValue( UNO_NAME_MISC_OBJ_NAME
                , uno::makeAny( rName ) );
        }
        catch( const uno::Exception& e )
        {
            ASSERT_EXCEPTION( e );
        }
    }
}

OUString AbstractShapeFactory::getShapeName( const uno::Reference< drawing::XShape >& xShape )
{
    OUString aRet;

    uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
    OSL_ENSURE(xProp.is(), "shape offers no XPropertySet");
    if( xProp.is())
    {
        try
        {
            xProp->getPropertyValue( UNO_NAME_MISC_OBJ_NAME ) >>= aRet;
        }
        catch( const uno::Exception& e )
        {
            ASSERT_EXCEPTION( e );
        }
    }

    return aRet;
}

uno::Any AbstractShapeFactory::makeTransformation( const awt::Point& rScreenPosition2D, double fRotationAnglePi )
{
    ::basegfx::B2DHomMatrix aM;
    //As autogrow is active the rectangle is automatically expanded to that side
    //to which the text is not adjusted.
    // aM.scale( 1, 1 ); Oops? A scale with this parameters is neutral, line commented out
    aM.rotate( fRotationAnglePi );
    aM.translate( rScreenPosition2D.X, rScreenPosition2D.Y );
    uno::Any aATransformation = uno::makeAny( B2DHomMatrixToHomogenMatrix3(aM) );
    return aATransformation;
}

OUString AbstractShapeFactory::getStackedString( const OUString& rString, bool bStacked )
{
    sal_Int32 nLen = rString.getLength();
    if(!bStacked || !nLen)
        return rString;

    OUStringBuffer aStackStr;

    //add a newline after each letter
    //as we do not no letters here add a newline after each char
    for( sal_Int32 nPosSrc=0; nPosSrc < nLen; nPosSrc++ )
    {
        if( nPosSrc )
            aStackStr.append( '\r' );
        aStackStr.append(rString[nPosSrc]);
    }
    return aStackStr.makeStringAndClear();
}

bool AbstractShapeFactory::hasPolygonAnyLines( drawing::PolyPolygonShape3D& rPoly)
{
    // #i67757# check all contained polygons, if at least one polygon contains 2 or more points, return true
    for( sal_Int32 nIdx = 0, nCount = rPoly.SequenceX.getLength(); nIdx < nCount; ++nIdx )
        if( rPoly.SequenceX[ nIdx ].getLength() > 1 )
            return true;
    return false;
}

bool AbstractShapeFactory::isPolygonEmptyOrSinglePoint( drawing::PolyPolygonShape3D& rPoly)
{
    // true, if empty polypolygon or one polygon with one point
    return (rPoly.SequenceX.getLength() == 0) ||
        ((rPoly.SequenceX.getLength() == 1) && (rPoly.SequenceX[0].getLength() <= 1));
}

void AbstractShapeFactory::closePolygon( drawing::PolyPolygonShape3D& rPoly)
{
    OSL_ENSURE( rPoly.SequenceX.getLength() <= 1, "AbstractShapeFactory::closePolygon - single polygon expected" );
    //add a last point == first point
    if(isPolygonEmptyOrSinglePoint(rPoly))
        return;
    drawing::Position3D aFirst(rPoly.SequenceX[0][0],rPoly.SequenceY[0][0],rPoly.SequenceZ[0][0]);
    AddPointToPoly( rPoly, aFirst );
}

awt::Size AbstractShapeFactory::calculateNewSizeRespectingAspectRatio(
         const awt::Size& rTargetSize
         , const awt::Size& rSourceSizeWithCorrectAspectRatio )
{
    awt::Size aNewSize;

    double fFactorWidth = double(rTargetSize.Width)/double(rSourceSizeWithCorrectAspectRatio.Width);
    double fFactorHeight = double(rTargetSize.Height)/double(rSourceSizeWithCorrectAspectRatio.Height);
    double fFactor = std::min(fFactorWidth,fFactorHeight);
    aNewSize.Width=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Width);
    aNewSize.Height=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Height);

    return aNewSize;
}

awt::Point AbstractShapeFactory::calculateTopLeftPositionToCenterObject(
           const awt::Point& rTargetAreaPosition
         , const awt::Size& rTargetAreaSize
         , const awt::Size& rObjectSize )
{
    awt::Point aNewPosition(rTargetAreaPosition);
    aNewPosition.X += static_cast<sal_Int32>(double(rTargetAreaSize.Width-rObjectSize.Width)/2.0);
    aNewPosition.Y += static_cast<sal_Int32>(double(rTargetAreaSize.Height-rObjectSize.Height)/2.0);
    return aNewPosition;
}

::basegfx::B2IRectangle AbstractShapeFactory::getRectangleOfShape(
        const uno::Reference< drawing::XShape >& xShape )
{
    ::basegfx::B2IRectangle aRet;

    if( xShape.is() )
    {
        awt::Point aPos = xShape->getPosition();
        awt::Size aSize = xShape->getSize();
        aRet = BaseGFXHelper::makeRectangle(aPos,aSize);
    }
    return aRet;

}

awt::Size AbstractShapeFactory::getSizeAfterRotation(
         const uno::Reference< drawing::XShape >& xShape, double fRotationAngleDegree )
{
    awt::Size aRet(0,0);
    if(xShape.is())
    {
        const awt::Size aSize( xShape->getSize() );

        if( ::rtl::math::approxEqual( fRotationAngleDegree, 0.0 ) )
            aRet = aSize;
        else
        {
            while(fRotationAngleDegree>=360.0)
                fRotationAngleDegree-=360.0;
            while(fRotationAngleDegree<0.0)
                fRotationAngleDegree+=360.0;
            if(fRotationAngleDegree>270.0)
                fRotationAngleDegree=360.0-fRotationAngleDegree;
            else if(fRotationAngleDegree>180.0)
                fRotationAngleDegree=fRotationAngleDegree-180.0;
            else if(fRotationAngleDegree>90.0)
                fRotationAngleDegree=180.0-fRotationAngleDegree;

            const double fAnglePi = fRotationAngleDegree*F_PI/180.0;

            aRet.Height = static_cast<sal_Int32>(
                aSize.Width*rtl::math::sin( fAnglePi )
                + aSize.Height*rtl::math::cos( fAnglePi ));
            aRet.Width = static_cast<sal_Int32>(
                aSize.Width*rtl::math::cos( fAnglePi )
                + aSize.Height*rtl::math::sin( fAnglePi ));
        }
    }
    return aRet;
}

void AbstractShapeFactory::removeSubShapes( const uno::Reference< drawing::XShapes >& xShapes )
{
    if( xShapes.is() )
    {
        sal_Int32 nSubCount = xShapes->getCount();
        uno::Reference< drawing::XShape > xShape;
        for( sal_Int32 nS = nSubCount; nS--; )
        {
            if( xShapes->getByIndex( nS ) >>= xShape )
                xShapes->remove( xShape );
        }
    }
}

}

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


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "app/surface/transport_dib.h"
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/ref_counted_memory.h"
#include "base/stringprintf.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/render_messages_params.h"
#include "chrome/renderer/render_widget_browsertest.h"
#include "gfx/codec/jpeg_codec.h"
#include "gfx/size.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
#include "third_party/WebKit/WebKit/chromium/public/WebView.h"

const int RenderWidgetTest::kNumBytesPerPixel = 4;
const int RenderWidgetTest::kLargeWidth = 1024;
const int RenderWidgetTest::kLargeHeight = 768;
const int RenderWidgetTest::kSmallWidth = 600;
const int RenderWidgetTest::kSmallHeight = 450;
const int RenderWidgetTest::kTextPositionX = 800;
const int RenderWidgetTest::kTextPositionY = 600;
const int RenderWidgetTest::kSequenceNum = 1;
const uint32 RenderWidgetTest::kRedARGB = 0xFFFF0000;

RenderWidgetTest::RenderWidgetTest() {}

void RenderWidgetTest::ResizeAndPaint(const gfx::Size& page_size,
                                      const gfx::Size& desired_size,
                                      SkBitmap* snapshot) {
  ASSERT_TRUE(snapshot);
  scoped_ptr<TransportDIB> pixels(
      TransportDIB::Create(
          page_size.width() * page_size.height() * kNumBytesPerPixel,
          kSequenceNum));
  view_->OnMsgPaintAtSize(pixels->handle(), kSequenceNum, page_size,
                          desired_size);
  ProcessPendingMessages();
  const IPC::Message* msg = render_thread_.sink().GetUniqueMessageMatching(
      ViewHostMsg_PaintAtSize_ACK::ID);
  ASSERT_NE(static_cast<IPC::Message*>(NULL), msg);
  ViewHostMsg_PaintAtSize_ACK::Param params;
  ViewHostMsg_PaintAtSize_ACK::Read(msg, &params);
  render_thread_.sink().ClearMessages();
  EXPECT_EQ(kSequenceNum, params.a);
  gfx::Size size = params.b;
  EXPECT_EQ(desired_size, size);

  SkBitmap tmp_bitmap;
  tmp_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
                       size.width(), size.height());
  tmp_bitmap.setPixels(pixels->memory());
  // Copy the pixels from the TransportDIB object to the given snapshot.
  ASSERT_TRUE(tmp_bitmap.copyTo(snapshot, SkBitmap::kARGB_8888_Config));
}

void RenderWidgetTest::TestResizeAndPaint() {
  // Hello World message is only visible if the view size is at least
  // kTextPositionX x kTextPositionY
  LoadHTML(StringPrintf(
      "
Hello World
",
      kTextPositionY, kTextPositionX).c_str());
  WebKit::WebSize old_size = view_->webview()->size();

  SkBitmap bitmap;
  // If we re-size the view to something smaller than where the 'Hello World'
  // text is displayed we won't see any text in the snapshot.  Hence,
  // the snapshot should not contain any red.
  gfx::Size size(kSmallWidth, kSmallHeight);
  ResizeAndPaint(size, size, &bitmap);
  // Make sure that the view has been re-sized to its old size.
  EXPECT_EQ(old_size, view_->webview()->size());
  EXPECT_EQ(kSmallWidth, bitmap.width());
  EXPECT_EQ(kSmallHeight, bitmap.height());
  EXPECT_FALSE(ImageContainsColor(bitmap, kRedARGB));

  // Since we ask for the view to be re-sized to something larger than where the
  // 'Hello World' text is written the text should be visible in the snapshot.
  // Hence, the snapshot should contain some red.
  size.SetSize(kLargeWidth, kLargeHeight);
  ResizeAndPaint(size, size, &bitmap);
  EXPECT_EQ(old_size, view_->webview()->size());
  EXPECT_EQ(kLargeWidth, bitmap.width());
  EXPECT_EQ(kLargeHeight, bitmap.height());
  EXPECT_TRUE(ImageContainsColor(bitmap, kRedARGB));

  // Even if the desired size is smaller than where the text is located we
  // should still see the 'Hello World' message since the view size is
  // still large enough.
  ResizeAndPaint(size, gfx::Size(kSmallWidth, kSmallHeight), &bitmap);
  EXPECT_EQ(old_size, view_->webview()->size());
  EXPECT_EQ(kSmallWidth, bitmap.width());
  EXPECT_EQ(kSmallHeight, bitmap.height());
  EXPECT_TRUE(ImageContainsColor(bitmap, kRedARGB));
}

bool RenderWidgetTest::ImageContainsColor(const SkBitmap& bitmap,
                                          uint32 argb_color) {
  SkAutoLockPixels lock(bitmap);
  bool ready = bitmap.readyToDraw();
  EXPECT_TRUE(ready);
  if (!ready) {
    return false;
  }
  for (int x = 0; x < bitmap.width(); ++x) {
    for (int y = 0; y < bitmap.height(); ++y) {
      if (argb_color == *bitmap.getAddr32(x, y)) {
        return true;
      }
    }
  }
  return false;
}

void RenderWidgetTest::OutputBitmapToFile(const SkBitmap& bitmap,
                                          const FilePath& file_path) {
  scoped_refptr<RefCountedBytes> bitmap_data = new RefCountedBytes();
  SkAutoLockPixels lock(bitmap);
  ASSERT_TRUE(gfx::JPEGCodec::Encode(
      reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
      gfx::JPEGCodec::FORMAT_BGRA,
      bitmap.width(),
      bitmap.height(),
      static_cast<int>(bitmap.rowBytes()),
      90 /* quality */,
      &bitmap_data->data));
  ASSERT_LT(0, file_util::WriteFile(
      file_path,
      reinterpret_cast<const char*>(bitmap_data->front()),
      bitmap_data->size()));
}

TEST_F(RenderWidgetTest, OnMsgPaintAtSize) {
  TestResizeAndPaint();
}
<commit_msg>Mark failing test OnMsgPaintAtSize failing TBR=noelutz BUG=none TEST=none Review URL: http://codereview.chromium.org/3470011<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "app/surface/transport_dib.h"
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/ref_counted_memory.h"
#include "base/stringprintf.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/render_messages_params.h"
#include "chrome/renderer/render_widget_browsertest.h"
#include "gfx/codec/jpeg_codec.h"
#include "gfx/size.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
#include "third_party/WebKit/WebKit/chromium/public/WebView.h"

const int RenderWidgetTest::kNumBytesPerPixel = 4;
const int RenderWidgetTest::kLargeWidth = 1024;
const int RenderWidgetTest::kLargeHeight = 768;
const int RenderWidgetTest::kSmallWidth = 600;
const int RenderWidgetTest::kSmallHeight = 450;
const int RenderWidgetTest::kTextPositionX = 800;
const int RenderWidgetTest::kTextPositionY = 600;
const int RenderWidgetTest::kSequenceNum = 1;
const uint32 RenderWidgetTest::kRedARGB = 0xFFFF0000;

RenderWidgetTest::RenderWidgetTest() {}

void RenderWidgetTest::ResizeAndPaint(const gfx::Size& page_size,
                                      const gfx::Size& desired_size,
                                      SkBitmap* snapshot) {
  ASSERT_TRUE(snapshot);
  scoped_ptr<TransportDIB> pixels(
      TransportDIB::Create(
          page_size.width() * page_size.height() * kNumBytesPerPixel,
          kSequenceNum));
  view_->OnMsgPaintAtSize(pixels->handle(), kSequenceNum, page_size,
                          desired_size);
  ProcessPendingMessages();
  const IPC::Message* msg = render_thread_.sink().GetUniqueMessageMatching(
      ViewHostMsg_PaintAtSize_ACK::ID);
  ASSERT_NE(static_cast<IPC::Message*>(NULL), msg);
  ViewHostMsg_PaintAtSize_ACK::Param params;
  ViewHostMsg_PaintAtSize_ACK::Read(msg, &params);
  render_thread_.sink().ClearMessages();
  EXPECT_EQ(kSequenceNum, params.a);
  gfx::Size size = params.b;
  EXPECT_EQ(desired_size, size);

  SkBitmap tmp_bitmap;
  tmp_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
                       size.width(), size.height());
  tmp_bitmap.setPixels(pixels->memory());
  // Copy the pixels from the TransportDIB object to the given snapshot.
  ASSERT_TRUE(tmp_bitmap.copyTo(snapshot, SkBitmap::kARGB_8888_Config));
}

void RenderWidgetTest::TestResizeAndPaint() {
  // Hello World message is only visible if the view size is at least
  // kTextPositionX x kTextPositionY
  LoadHTML(StringPrintf(
      "
Hello World
",
      kTextPositionY, kTextPositionX).c_str());
  WebKit::WebSize old_size = view_->webview()->size();

  SkBitmap bitmap;
  // If we re-size the view to something smaller than where the 'Hello World'
  // text is displayed we won't see any text in the snapshot.  Hence,
  // the snapshot should not contain any red.
  gfx::Size size(kSmallWidth, kSmallHeight);
  ResizeAndPaint(size, size, &bitmap);
  // Make sure that the view has been re-sized to its old size.
  EXPECT_EQ(old_size, view_->webview()->size());
  EXPECT_EQ(kSmallWidth, bitmap.width());
  EXPECT_EQ(kSmallHeight, bitmap.height());
  EXPECT_FALSE(ImageContainsColor(bitmap, kRedARGB));

  // Since we ask for the view to be re-sized to something larger than where the
  // 'Hello World' text is written the text should be visible in the snapshot.
  // Hence, the snapshot should contain some red.
  size.SetSize(kLargeWidth, kLargeHeight);
  ResizeAndPaint(size, size, &bitmap);
  EXPECT_EQ(old_size, view_->webview()->size());
  EXPECT_EQ(kLargeWidth, bitmap.width());
  EXPECT_EQ(kLargeHeight, bitmap.height());
  EXPECT_TRUE(ImageContainsColor(bitmap, kRedARGB));

  // Even if the desired size is smaller than where the text is located we
  // should still see the 'Hello World' message since the view size is
  // still large enough.
  ResizeAndPaint(size, gfx::Size(kSmallWidth, kSmallHeight), &bitmap);
  EXPECT_EQ(old_size, view_->webview()->size());
  EXPECT_EQ(kSmallWidth, bitmap.width());
  EXPECT_EQ(kSmallHeight, bitmap.height());
  EXPECT_TRUE(ImageContainsColor(bitmap, kRedARGB));
}

bool RenderWidgetTest::ImageContainsColor(const SkBitmap& bitmap,
                                          uint32 argb_color) {
  SkAutoLockPixels lock(bitmap);
  bool ready = bitmap.readyToDraw();
  EXPECT_TRUE(ready);
  if (!ready) {
    return false;
  }
  for (int x = 0; x < bitmap.width(); ++x) {
    for (int y = 0; y < bitmap.height(); ++y) {
      if (argb_color == *bitmap.getAddr32(x, y)) {
        return true;
      }
    }
  }
  return false;
}

void RenderWidgetTest::OutputBitmapToFile(const SkBitmap& bitmap,
                                          const FilePath& file_path) {
  scoped_refptr<RefCountedBytes> bitmap_data = new RefCountedBytes();
  SkAutoLockPixels lock(bitmap);
  ASSERT_TRUE(gfx::JPEGCodec::Encode(
      reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
      gfx::JPEGCodec::FORMAT_BGRA,
      bitmap.width(),
      bitmap.height(),
      static_cast<int>(bitmap.rowBytes()),
      90 /* quality */,
      &bitmap_data->data));
  ASSERT_LT(0, file_util::WriteFile(
      file_path,
      reinterpret_cast<const char*>(bitmap_data->front()),
      bitmap_data->size()));
}

TEST_F(RenderWidgetTest, FAILS_OnMsgPaintAtSize) {
  TestResizeAndPaint();
}
<|endoftext|>


<commit_before><commit_msg>coverity#708124 Uninitialized scalar field<commit_after><|endoftext|>


<commit_before>#include "io_socket.h"

#include <cstdlib>
#include <cstring>

#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>

namespace cppio
{

UnixSocket::UnixSocket(const std::string& address) : m_address(address)
{
	m_socket = socket(AF_UNIX, SOCK_STREAM, 0);
	if(m_socket < 0)
		throw IoException(std::string("Unable to create socket: " + std::to_string(m_socket)));
}

UnixSocket::UnixSocket(int fd, const std::string& address)
{
	m_socket = fd;
	m_address = address;
}

UnixSocket::~UnixSocket()
{
	close(m_socket);
	unlink(m_address.c_str());
}

void UnixSocket::connect()
{
	sockaddr serverName;
	serverName.sa_family = AF_UNIX;
	strncpy(serverName.sa_data, m_address.c_str(), sizeof(serverName.sa_data));

	int rc = ::connect(m_socket, &serverName, strlen(serverName.sa_data) + sizeof(serverName.sa_family));
	if(rc < 0)
		throw IoException(std::string("Unable to connect to socket: " + std::to_string(rc) + "/" + std::to_string(errno)));
}

ssize_t UnixSocket::read(void* buffer, size_t buflen)
{
	ssize_t rc = ::read(m_socket, buffer, buflen);
	if(rc < 0)
	{
		if((errno == ECONNRESET) || (errno == ENOTCONN))
			throw ConnectionLost("");
		return 0;
	}
	else if(rc == 0)
	{
		if(errno != ETIMEDOUT)
			throw ConnectionLost("");
	}
	return rc;
}

ssize_t UnixSocket::write(void* buffer, size_t buflen)
{
	ssize_t rc = ::write(m_socket, buffer, buflen);
	return rc;
}

void UnixSocket::setOption(LineOption option, void* data)
{
	switch(option)
	{
		case LineOption::ReceiveTimeout:
			{
				int msecs = *(int*)data;
				int secs = msecs / 1000;
				int restMsecs = msecs - secs * 1000;
				struct timeval timeout;
				timeout.tv_sec = secs;
				timeout.tv_usec = restMsecs * 1000;

				setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
							sizeof(timeout));
			}
			break;

		case LineOption::SendTimeout:
			{
				int msecs = *(int*)data;
				int secs = msecs / 1000;
				int restMsecs = msecs - secs * 1000;
				struct timeval timeout;
				timeout.tv_sec = secs;
				timeout.tv_usec = restMsecs * 1000;

				setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout,
							sizeof(timeout));
			}
			break;
		default:
			throw UnsupportedOption("");
	}
}

UnixSocketAcceptor::UnixSocketAcceptor(const std::string& address) : m_address(address)
{
	m_socket = socket(AF_UNIX, SOCK_STREAM, 0);
	if(m_socket < 0)
		throw IoException(std::string("Unable to create socket: " + std::to_string(m_socket)));

	sockaddr serverName;
	serverName.sa_family = AF_UNIX;
	strncpy(serverName.sa_data, m_address.c_str(), sizeof(serverName.sa_data));

	int rc = bind(m_socket, &serverName, strlen(serverName.sa_data) + sizeof(serverName.sa_family));
	if(rc < 0)
		throw IoException(std::string("Unable to bind socket: " + std::to_string(rc)));

	rc = listen(m_socket, 10);
	if(rc < 0)
	{
		close(m_socket);
		unlink(m_address.c_str());
		throw IoException(std::string("Unable to listen socket: " + std::to_string(rc)));
	}
}

UnixSocketAcceptor::~UnixSocketAcceptor()
{
	close(m_socket);
	unlink(m_address.c_str());
}

std::shared_ptr<IoLine> UnixSocketAcceptor::waitConnection(const std::chrono::milliseconds& timeout)
{
	sockaddr addr;
	socklen_t clen = sizeof(addr);
	int newsock = accept(m_socket, &addr, &clen);
	if(newsock > 0)
	{
		return std::make_shared<UnixSocket>(newsock, "");
	}
	return std::shared_ptr<IoLine>();
}

UnixSocketFactory::~UnixSocketFactory()
{
}

bool UnixSocketFactory::supportsScheme(const std::string& scheme)
{
	return scheme == "local";
}

std::shared_ptr<IoLine> UnixSocketFactory::createClient(const std::string& address)
{
	auto socket = std::make_shared<UnixSocket>(address);
	if(socket)
		socket->connect();
	return socket;
}

std::shared_ptr<IoAcceptor> UnixSocketFactory::createServer(const std::string& address)
{
	return std::make_shared<UnixSocketAcceptor>(address);
}

///////

TcpSocket::TcpSocket(const std::string& address) : m_address(address)
{
	m_socket = socket(AF_INET, SOCK_STREAM, 0);
	if(m_socket < 0)
		throw IoException(std::string("Unable to create socket: " + std::to_string(m_socket)));
}

TcpSocket::TcpSocket(int fd, const std::string& address)
{
	m_socket = fd;
	m_address = address;
}

TcpSocket::~TcpSocket()
{
	close(m_socket);
}

void TcpSocket::connect()
{
	auto semicolon = m_address.find(':');
	auto host = m_address.substr(0, semicolon);
	auto port = atoi(m_address.substr(semicolon + 1).c_str());
	sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr(host.c_str());
	addr.sin_port = htons(port);

	int rc = ::connect(m_socket, (sockaddr*)&addr, sizeof(addr));
	if(rc < 0)
		throw IoException(std::string("Unable to connect socket: " + std::to_string(rc)));
}

ssize_t TcpSocket::read(void* buffer, size_t buflen)
{
	ssize_t rc = ::read(m_socket, buffer, buflen);
	if(rc < 0)
	{
		if((errno == ECONNRESET) || (errno == ENOTCONN))
			throw ConnectionLost("");
		return 0;
	}
	else if(rc == 0)
	{
		if(errno != ETIMEDOUT)
			throw ConnectionLost("");
	}
	return rc;
}

ssize_t TcpSocket::write(void* buffer, size_t buflen)
{
	ssize_t rc = ::write(m_socket, buffer, buflen);
	return rc;
}

void TcpSocket::setOption(LineOption option, void* data)
{
	switch(option)
	{
		case LineOption::ReceiveTimeout:
			{
				int msecs = *(int*)data;
				int secs = msecs / 1000;
				int restMsecs = msecs - secs * 1000;
				struct timeval timeout;
				timeout.tv_sec = secs;
				timeout.tv_usec = restMsecs * 1000;

				setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
							sizeof(timeout));
			}
			break;

		case LineOption::SendTimeout:
			{
				int msecs = *(int*)data;
				int secs = msecs / 1000;
				int restMsecs = msecs - secs * 1000;
				struct timeval timeout;
				timeout.tv_sec = secs;
				timeout.tv_usec = restMsecs * 1000;

				setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout,
							sizeof(timeout));
			}
			break;
		default:
			throw UnsupportedOption("");
	}
}

TcpSocketAcceptor::TcpSocketAcceptor(const std::string& address) : m_address(address)
{
	m_socket = socket(AF_INET, SOCK_STREAM, 0);
	if(m_socket < 0)
		throw IoException(std::string("Unable to create socket: " + std::to_string(m_socket)));

	int enable = 1;
	if(setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0)
		throw IoException(std::string("Unable to set socket option: " + std::to_string(m_socket)));

	auto semicolon = m_address.find(':');
	auto host = m_address.substr(0, semicolon);
	auto port = atoi(m_address.substr(semicolon + 1).c_str());
	sockaddr_in serverName;
	memset(&serverName, 0, sizeof(serverName));
	serverName.sin_family = AF_INET;
	if(host != "*")
		serverName.sin_addr.s_addr = inet_addr(host.c_str());
	else
		serverName.sin_addr.s_addr = INADDR_ANY;
	serverName.sin_port = htons(port);

	int rc = bind(m_socket, (sockaddr*)&serverName, sizeof(serverName));
	if(rc < 0)
		throw IoException(std::string("Unable to bind tcp socket: " + std::to_string(rc)) + "/" + std::to_string(errno));

	rc = listen(m_socket, 10);
	if(rc < 0)
	{
		close(m_socket);
		throw IoException(std::string("Unable to listen socket: " + std::to_string(rc)));
	}
}

TcpSocketAcceptor::~TcpSocketAcceptor()
{
	close(m_socket);
}

std::shared_ptr<IoLine> TcpSocketAcceptor::waitConnection(const std::chrono::milliseconds& timeout)
{
	sockaddr addr;
	socklen_t clen = sizeof(addr);
	int newsock = accept(m_socket, &addr, &clen);
	if(newsock > 0)
	{
		return std::make_shared<TcpSocket>(newsock, "");
	}
	return std::shared_ptr<IoLine>();
}

TcpSocketFactory::~TcpSocketFactory()
{
}

bool TcpSocketFactory::supportsScheme(const std::string& scheme)
{
	return scheme == "tcp";
}

std::shared_ptr<IoLine> TcpSocketFactory::createClient(const std::string& address)
{
	auto socket = std::make_shared<TcpSocket>(address);
	if(socket)
		socket->connect();
	return socket;
}

std::shared_ptr<IoAcceptor> TcpSocketFactory::createServer(const std::string& address)
{
	return std::make_shared<TcpSocketAcceptor>(address);
}

}

<commit_msg>Error message++<commit_after>#include "io_socket.h"

#include <cstdlib>
#include <cstring>

#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>

namespace cppio
{

UnixSocket::UnixSocket(const std::string& address) : m_address(address)
{
	m_socket = socket(AF_UNIX, SOCK_STREAM, 0);
	if(m_socket < 0)
		throw IoException(std::string("Unable to create socket: " + std::to_string(m_socket)));
}

UnixSocket::UnixSocket(int fd, const std::string& address)
{
	m_socket = fd;
	m_address = address;
}

UnixSocket::~UnixSocket()
{
	close(m_socket);
	unlink(m_address.c_str());
}

void UnixSocket::connect()
{
	sockaddr serverName;
	serverName.sa_family = AF_UNIX;
	strncpy(serverName.sa_data, m_address.c_str(), sizeof(serverName.sa_data));

	int rc = ::connect(m_socket, &serverName, strlen(serverName.sa_data) + sizeof(serverName.sa_family));
	if(rc < 0)
		throw IoException(std::string("Unable to connect to socket: " + std::to_string(rc) + "/" + std::to_string(errno)));
}

ssize_t UnixSocket::read(void* buffer, size_t buflen)
{
	ssize_t rc = ::read(m_socket, buffer, buflen);
	if(rc < 0)
	{
		if((errno == ECONNRESET) || (errno == ENOTCONN))
			throw ConnectionLost("");
		return 0;
	}
	else if(rc == 0)
	{
		if(errno != ETIMEDOUT)
			throw ConnectionLost("");
	}
	return rc;
}

ssize_t UnixSocket::write(void* buffer, size_t buflen)
{
	ssize_t rc = ::write(m_socket, buffer, buflen);
	return rc;
}

void UnixSocket::setOption(LineOption option, void* data)
{
	switch(option)
	{
		case LineOption::ReceiveTimeout:
			{
				int msecs = *(int*)data;
				int secs = msecs / 1000;
				int restMsecs = msecs - secs * 1000;
				struct timeval timeout;
				timeout.tv_sec = secs;
				timeout.tv_usec = restMsecs * 1000;

				setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
							sizeof(timeout));
			}
			break;

		case LineOption::SendTimeout:
			{
				int msecs = *(int*)data;
				int secs = msecs / 1000;
				int restMsecs = msecs - secs * 1000;
				struct timeval timeout;
				timeout.tv_sec = secs;
				timeout.tv_usec = restMsecs * 1000;

				setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout,
							sizeof(timeout));
			}
			break;
		default:
			throw UnsupportedOption("");
	}
}

UnixSocketAcceptor::UnixSocketAcceptor(const std::string& address) : m_address(address)
{
	m_socket = socket(AF_UNIX, SOCK_STREAM, 0);
	if(m_socket < 0)
		throw IoException(std::string("Unable to create socket: " + std::to_string(m_socket)));

	sockaddr serverName;
	serverName.sa_family = AF_UNIX;
	strncpy(serverName.sa_data, m_address.c_str(), sizeof(serverName.sa_data));

	int rc = bind(m_socket, &serverName, strlen(serverName.sa_data) + sizeof(serverName.sa_family));
	if(rc < 0)
		throw IoException(std::string("Unable to bind socket: " + std::to_string(rc)));

	rc = listen(m_socket, 10);
	if(rc < 0)
	{
		close(m_socket);
		unlink(m_address.c_str());
		throw IoException(std::string("Unable to listen socket: " + std::to_string(rc)));
	}
}

UnixSocketAcceptor::~UnixSocketAcceptor()
{
	close(m_socket);
	unlink(m_address.c_str());
}

std::shared_ptr<IoLine> UnixSocketAcceptor::waitConnection(const std::chrono::milliseconds& timeout)
{
	sockaddr addr;
	socklen_t clen = sizeof(addr);
	int newsock = accept(m_socket, &addr, &clen);
	if(newsock > 0)
	{
		return std::make_shared<UnixSocket>(newsock, "");
	}
	return std::shared_ptr<IoLine>();
}

UnixSocketFactory::~UnixSocketFactory()
{
}

bool UnixSocketFactory::supportsScheme(const std::string& scheme)
{
	return scheme == "local";
}

std::shared_ptr<IoLine> UnixSocketFactory::createClient(const std::string& address)
{
	auto socket = std::make_shared<UnixSocket>(address);
	if(socket)
		socket->connect();
	return socket;
}

std::shared_ptr<IoAcceptor> UnixSocketFactory::createServer(const std::string& address)
{
	return std::make_shared<UnixSocketAcceptor>(address);
}

///////

TcpSocket::TcpSocket(const std::string& address) : m_address(address)
{
	m_socket = socket(AF_INET, SOCK_STREAM, 0);
	if(m_socket < 0)
		throw IoException(std::string("Unable to create socket: " + std::to_string(m_socket)));
}

TcpSocket::TcpSocket(int fd, const std::string& address)
{
	m_socket = fd;
	m_address = address;
}

TcpSocket::~TcpSocket()
{
	close(m_socket);
}

void TcpSocket::connect()
{
	auto semicolon = m_address.find(':');
	auto host = m_address.substr(0, semicolon);
	auto port = atoi(m_address.substr(semicolon + 1).c_str());
	sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr(host.c_str());
	addr.sin_port = htons(port);

	int rc = ::connect(m_socket, (sockaddr*)&addr, sizeof(addr));
	if(rc < 0)
		throw IoException(std::string("Unable to connect socket: " + std::to_string(rc) + "/" + std::to_string(errno)));
}

ssize_t TcpSocket::read(void* buffer, size_t buflen)
{
	ssize_t rc = ::read(m_socket, buffer, buflen);
	if(rc < 0)
	{
		if((errno == ECONNRESET) || (errno == ENOTCONN))
			throw ConnectionLost("");
		return 0;
	}
	else if(rc == 0)
	{
		if(errno != ETIMEDOUT)
			throw ConnectionLost("");
	}
	return rc;
}

ssize_t TcpSocket::write(void* buffer, size_t buflen)
{
	ssize_t rc = ::write(m_socket, buffer, buflen);
	return rc;
}

void TcpSocket::setOption(LineOption option, void* data)
{
	switch(option)
	{
		case LineOption::ReceiveTimeout:
			{
				int msecs = *(int*)data;
				int secs = msecs / 1000;
				int restMsecs = msecs - secs * 1000;
				struct timeval timeout;
				timeout.tv_sec = secs;
				timeout.tv_usec = restMsecs * 1000;

				setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
							sizeof(timeout));
			}
			break;

		case LineOption::SendTimeout:
			{
				int msecs = *(int*)data;
				int secs = msecs / 1000;
				int restMsecs = msecs - secs * 1000;
				struct timeval timeout;
				timeout.tv_sec = secs;
				timeout.tv_usec = restMsecs * 1000;

				setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout,
							sizeof(timeout));
			}
			break;
		default:
			throw UnsupportedOption("");
	}
}

TcpSocketAcceptor::TcpSocketAcceptor(const std::string& address) : m_address(address)
{
	m_socket = socket(AF_INET, SOCK_STREAM, 0);
	if(m_socket < 0)
		throw IoException(std::string("Unable to create socket: " + std::to_string(m_socket)));

	int enable = 1;
	if(setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0)
		throw IoException(std::string("Unable to set socket option: " + std::to_string(m_socket)));

	auto semicolon = m_address.find(':');
	auto host = m_address.substr(0, semicolon);
	auto port = atoi(m_address.substr(semicolon + 1).c_str());
	sockaddr_in serverName;
	memset(&serverName, 0, sizeof(serverName));
	serverName.sin_family = AF_INET;
	if(host != "*")
		serverName.sin_addr.s_addr = inet_addr(host.c_str());
	else
		serverName.sin_addr.s_addr = INADDR_ANY;
	serverName.sin_port = htons(port);

	int rc = bind(m_socket, (sockaddr*)&serverName, sizeof(serverName));
	if(rc < 0)
		throw IoException(std::string("Unable to bind tcp socket: " + std::to_string(rc)) + "/" + std::to_string(errno));

	rc = listen(m_socket, 10);
	if(rc < 0)
	{
		close(m_socket);
		throw IoException(std::string("Unable to listen socket: " + std::to_string(rc)));
	}
}

TcpSocketAcceptor::~TcpSocketAcceptor()
{
	close(m_socket);
}

std::shared_ptr<IoLine> TcpSocketAcceptor::waitConnection(const std::chrono::milliseconds& timeout)
{
	sockaddr addr;
	socklen_t clen = sizeof(addr);
	int newsock = accept(m_socket, &addr, &clen);
	if(newsock > 0)
	{
		return std::make_shared<TcpSocket>(newsock, "");
	}
	return std::shared_ptr<IoLine>();
}

TcpSocketFactory::~TcpSocketFactory()
{
}

bool TcpSocketFactory::supportsScheme(const std::string& scheme)
{
	return scheme == "tcp";
}

std::shared_ptr<IoLine> TcpSocketFactory::createClient(const std::string& address)
{
	auto socket = std::make_shared<TcpSocket>(address);
	if(socket)
		socket->connect();
	return socket;
}

std::shared_ptr<IoAcceptor> TcpSocketFactory::createServer(const std::string& address)
{
	return std::make_shared<TcpSocketAcceptor>(address);
}

}

<|endoftext|>