<commit_before>// Cylinder.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"
#include "Cylinder.h"
#include "../interface/PropertyVertex.h"
#include "../interface/PropertyDouble.h"
#include "../interface/PropertyLength.h"
#include "Gripper.h"
#include "MarkedList.h"

CCylinder::CCylinder(const gp_Ax2& pos, double radius, double height, const wxChar* title, const HeeksColor& col):CSolid(BRepPrimAPI_MakeCylinder(pos, radius, height), title, col), m_pos(pos), m_radius(radius), m_height(height)
{
}

CCylinder::CCylinder(const TopoDS_Solid &solid, const wxChar* title, const HeeksColor& col):CSolid(solid, title, col), m_pos(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1), gp_Dir(1, 0, 0)), m_radius(0.0), m_height(0.0)
{
}

HeeksObj *CCylinder::MakeACopy(void)const
{
	return new CCylinder(*this);
}

static void on_set_centre(const double *vt, HeeksObj* object){
	gp_Trsf mat;
	mat.SetTranslation ( gp_Vec ( ((CCylinder*)object)->m_pos.Location(), make_point(vt) ) );
	((CCylinder*)object)->m_pos.Transform(mat);
}

static void on_set_radius(double value, HeeksObj* object){
	((CCylinder*)object)->m_radius = value;
}

static void on_set_height(double value, HeeksObj* object){
	((CCylinder*)object)->m_height = value;
}

bool CCylinder::ModifyByMatrix(const double* m){
	gp_Trsf mat = make_matrix(m);
	gp_Ax2 new_pos = m_pos.Transformed(mat);
	double scale = gp_Vec(1, 0, 0).Transformed(mat).Magnitude();
	double new_radius = fabs(m_radius * scale);
	double new_height = fabs(m_height * scale);
	CCylinder* new_object = new CCylinder(new_pos, new_radius, new_height, m_title.c_str(), m_color);
	new_object->CopyIDsFrom(this);
	wxGetApp().AddUndoably(new_object, Owner(), NULL);
	if(wxGetApp().m_marked_list->ObjectMarked(this))wxGetApp().m_marked_list->Add(new_object, true);
	wxGetApp().DeleteUndoably(this);
	return true;
}

void CCylinder::GetProperties(std::list<Property *> *list)
{
	double c[3];
	extract(m_pos.Location(), c);
	list->push_back(new PropertyVertex(_("centre pos"), c, this, on_set_centre));
	list->push_back(new PropertyLength(_("radius"), m_radius, this, on_set_radius));
	list->push_back(new PropertyLength(_("height"), m_height, this, on_set_height));

	CSolid::GetProperties(list);
}

void CCylinder::GetGripperPositions(std::list<GripData> *list, bool just_for_endof)
{
	gp_Pnt o = m_pos.Location();
	gp_Pnt px(o.XYZ() + m_pos.XDirection().XYZ() * m_radius);
	gp_Dir z_dir = m_pos.XDirection() ^ m_pos.YDirection();
	gp_Pnt pyz(o.XYZ() + m_pos.YDirection().XYZ() * m_radius + z_dir.XYZ() * m_height);
	gp_Pnt pmxz(o.XYZ() + m_pos.XDirection().XYZ() * (-m_radius) + z_dir.XYZ() * m_height);
	gp_Pnt pz(o.XYZ() + z_dir.XYZ() * m_height);
	list->push_back(GripData(GripperTypeTranslate,o.X(),o.Y(),o.Z(),NULL));
	list->push_back(GripData(GripperTypeObjectScaleXY,px.X(),px.Y(),px.Z(),NULL));
	list->push_back(GripData(GripperTypeRotateObject,pyz.X(),pyz.Y(),pyz.Z(),NULL));
	list->push_back(GripData(GripperTypeRotateObject,pmxz.X(),pmxz.Y(),pmxz.Z(),NULL));
	list->push_back(GripData(GripperTypeObjectScaleZ,pz.X(),pz.Y(),pz.Z(),NULL));
}

void CCylinder::OnApplyProperties()
{
	CCylinder* new_object = new CCylinder(m_pos, m_radius, m_height, m_title.c_str(), m_color);
	new_object->CopyIDsFrom(this);
	wxGetApp().StartHistory();
	wxGetApp().AddUndoably(new_object, NULL, NULL);
	wxGetApp().DeleteUndoably(this);
	wxGetApp().EndHistory();
	wxGetApp().m_marked_list->Clear(true);
	if(wxGetApp().m_marked_list->ObjectMarked(this))wxGetApp().m_marked_list->Add(new_object, true);
	wxGetApp().Repaint();
}

bool CCylinder::GetScaleAboutMatrix(double *m)
{
	gp_Trsf mat = make_matrix(m_pos.Location(), m_pos.XDirection(), m_pos.YDirection());
	extract(mat, m);
	return true;
}

bool CCylinder::Stretch(const double *p, const double* shift, void* data)
{
	gp_Pnt vp = make_point(p);
	gp_Vec vshift = make_vector(shift);

	gp_Pnt o = m_pos.Location();
	gp_Pnt px(o.XYZ() + m_pos.XDirection().XYZ() * m_radius);
	gp_Dir z_dir = m_pos.XDirection() ^ m_pos.YDirection();
	gp_Pnt pz(o.XYZ() + z_dir.XYZ() * m_height);

	bool make_a_new_cylinder = false;

	if(px.IsEqual(vp, wxGetApp().m_geom_tol)){
		px = px.XYZ() + vshift.XYZ();
		double new_x = gp_Vec(px.XYZ()) * gp_Vec(m_pos.XDirection()) - gp_Vec(o.XYZ()) * gp_Vec(m_pos.XDirection());
		double new_y = gp_Vec(px.XYZ()) * gp_Vec(m_pos.YDirection()) - gp_Vec(o.XYZ()) * gp_Vec(m_pos.YDirection());
		make_a_new_cylinder = true;
		m_radius = sqrt(new_x * new_x + new_y * new_y);
	}
	else if(pz.IsEqual(vp, wxGetApp().m_geom_tol)){
		pz = pz.XYZ() + vshift.XYZ();
		double new_height = gp_Vec(pz.XYZ()) * gp_Vec(z_dir) - gp_Vec(o.XYZ()) * gp_Vec(z_dir);
		if(new_height > 0){
			make_a_new_cylinder = true;
			m_height = new_height;
		}
	}

	if(make_a_new_cylinder)
	{
		CCylinder* new_object = new CCylinder(m_pos, m_radius, m_height, m_title.c_str(), m_color);
		new_object->CopyIDsFrom(this);
		wxGetApp().StartHistory();
		wxGetApp().AddUndoably(new_object, NULL, NULL);
		wxGetApp().DeleteUndoably(this);
		wxGetApp().EndHistory();
		wxGetApp().m_marked_list->Clear(true);
		wxGetApp().m_marked_list->Add(new_object, true);
	}

	return true;
}

void CCylinder::SetXMLElement(TiXmlElement* element)
{
	const gp_Pnt& l = m_pos.Location();
	element->SetDoubleAttribute("lx", l.X());
	element->SetDoubleAttribute("ly", l.Y());
	element->SetDoubleAttribute("lz", l.Z());

	const gp_Dir& d = m_pos.Direction();
	element->SetDoubleAttribute("dx", d.X());
	element->SetDoubleAttribute("dy", d.Y());
	element->SetDoubleAttribute("dz", d.Z());

	const gp_Dir& x = m_pos.XDirection();
	element->SetDoubleAttribute("xx", x.X());
	element->SetDoubleAttribute("xy", x.Y());
	element->SetDoubleAttribute("xz", x.Z());

	element->SetDoubleAttribute("r", m_radius);
	element->SetDoubleAttribute("h", m_height);

	CSolid::SetXMLElement(element);
}

void CCylinder::SetFromXMLElement(TiXmlElement* pElem)
{
	// get the attributes
	double l[3] = {0, 0, 0};
	double d[3] = {0, 0, 1};
	double x[3] = {1, 0, 0};

	for(TiXmlAttribute* a = pElem->FirstAttribute(); a; a = a->Next())
	{
		std::string name(a->Name());
		if(name == "lx")	 {l[0] = a->DoubleValue();}
		else if(name == "ly"){l[1] = a->DoubleValue();}
		else if(name == "lz"){l[2] = a->DoubleValue();}

		else if(name == "dx"){d[0] = a->DoubleValue();}
		else if(name == "dy"){d[1] = a->DoubleValue();}
		else if(name == "dz"){d[2] = a->DoubleValue();}

		else if(name == "xx"){x[0] = a->DoubleValue();}
		else if(name == "xy"){x[1] = a->DoubleValue();}
		else if(name == "xz"){x[2] = a->DoubleValue();}

		else if(name == "r"){m_radius = a->DoubleValue();}
		else if(name == "h"){m_height = a->DoubleValue();}
	}

	m_pos = gp_Ax2(make_point(l), make_vector(d), make_vector(x));

	CSolid::SetFromXMLElement(pElem);
}
<commit_msg>fixed  Issue 197:  	 Crash with negative length cylinder<commit_after>// Cylinder.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"
#include "Cylinder.h"
#include "../interface/PropertyVertex.h"
#include "../interface/PropertyDouble.h"
#include "../interface/PropertyLength.h"
#include "Gripper.h"
#include "MarkedList.h"

static TopoDS_Solid MakeCylinder(const gp_Ax2& pos, double radius, double height)
{
	gp_Ax2 pos2 = pos;
	if(height<0)
	{
		pos2 = gp_Ax2(pos.Location(), -(pos.Direction()));
		height = fabs(height);
	}

	return BRepPrimAPI_MakeCylinder(pos2, radius, height);
}

CCylinder::CCylinder(const gp_Ax2& pos, double radius, double height, const wxChar* title, const HeeksColor& col):CSolid(MakeCylinder(pos, radius, height), title, col), m_pos(pos), m_radius(radius), m_height(height)
{
}

CCylinder::CCylinder(const TopoDS_Solid &solid, const wxChar* title, const HeeksColor& col):CSolid(solid, title, col), m_pos(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1), gp_Dir(1, 0, 0)), m_radius(0.0), m_height(0.0)
{
}

HeeksObj *CCylinder::MakeACopy(void)const
{
	return new CCylinder(*this);
}

static void on_set_centre(const double *vt, HeeksObj* object){
	gp_Trsf mat;
	mat.SetTranslation ( gp_Vec ( ((CCylinder*)object)->m_pos.Location(), make_point(vt) ) );
	((CCylinder*)object)->m_pos.Transform(mat);
}

static void on_set_radius(double value, HeeksObj* object){
	((CCylinder*)object)->m_radius = value;
}

static void on_set_height(double value, HeeksObj* object){
	((CCylinder*)object)->m_height = value;
}

bool CCylinder::ModifyByMatrix(const double* m){
	gp_Trsf mat = make_matrix(m);
	gp_Ax2 new_pos = m_pos.Transformed(mat);
	double scale = gp_Vec(1, 0, 0).Transformed(mat).Magnitude();
	double new_radius = fabs(m_radius * scale);
	double new_height = fabs(m_height * scale);
	CCylinder* new_object = new CCylinder(new_pos, new_radius, new_height, m_title.c_str(), m_color);
	new_object->CopyIDsFrom(this);
	wxGetApp().AddUndoably(new_object, Owner(), NULL);
	if(wxGetApp().m_marked_list->ObjectMarked(this))wxGetApp().m_marked_list->Add(new_object, true);
	wxGetApp().DeleteUndoably(this);
	return true;
}

void CCylinder::GetProperties(std::list<Property *> *list)
{
	double c[3];
	extract(m_pos.Location(), c);
	list->push_back(new PropertyVertex(_("centre pos"), c, this, on_set_centre));
	list->push_back(new PropertyLength(_("radius"), m_radius, this, on_set_radius));
	list->push_back(new PropertyLength(_("height"), m_height, this, on_set_height));

	CSolid::GetProperties(list);
}

void CCylinder::GetGripperPositions(std::list<GripData> *list, bool just_for_endof)
{
	gp_Pnt o = m_pos.Location();
	gp_Pnt px(o.XYZ() + m_pos.XDirection().XYZ() * m_radius);
	gp_Dir z_dir = m_pos.XDirection() ^ m_pos.YDirection();
	gp_Pnt pyz(o.XYZ() + m_pos.YDirection().XYZ() * m_radius + z_dir.XYZ() * m_height);
	gp_Pnt pmxz(o.XYZ() + m_pos.XDirection().XYZ() * (-m_radius) + z_dir.XYZ() * m_height);
	gp_Pnt pz(o.XYZ() + z_dir.XYZ() * m_height);
	list->push_back(GripData(GripperTypeTranslate,o.X(),o.Y(),o.Z(),NULL));
	list->push_back(GripData(GripperTypeObjectScaleXY,px.X(),px.Y(),px.Z(),NULL));
	list->push_back(GripData(GripperTypeRotateObject,pyz.X(),pyz.Y(),pyz.Z(),NULL));
	list->push_back(GripData(GripperTypeRotateObject,pmxz.X(),pmxz.Y(),pmxz.Z(),NULL));
	list->push_back(GripData(GripperTypeObjectScaleZ,pz.X(),pz.Y(),pz.Z(),NULL));
}

void CCylinder::OnApplyProperties()
{
	CCylinder* new_object = new CCylinder(m_pos, m_radius, m_height, m_title.c_str(), m_color);
	new_object->CopyIDsFrom(this);
	wxGetApp().StartHistory();
	wxGetApp().AddUndoably(new_object, NULL, NULL);
	wxGetApp().DeleteUndoably(this);
	wxGetApp().EndHistory();
	wxGetApp().m_marked_list->Clear(true);
	if(wxGetApp().m_marked_list->ObjectMarked(this))wxGetApp().m_marked_list->Add(new_object, true);
	wxGetApp().Repaint();
}

bool CCylinder::GetScaleAboutMatrix(double *m)
{
	gp_Trsf mat = make_matrix(m_pos.Location(), m_pos.XDirection(), m_pos.YDirection());
	extract(mat, m);
	return true;
}

bool CCylinder::Stretch(const double *p, const double* shift, void* data)
{
	gp_Pnt vp = make_point(p);
	gp_Vec vshift = make_vector(shift);

	gp_Pnt o = m_pos.Location();
	gp_Pnt px(o.XYZ() + m_pos.XDirection().XYZ() * m_radius);
	gp_Dir z_dir = m_pos.XDirection() ^ m_pos.YDirection();
	gp_Pnt pz(o.XYZ() + z_dir.XYZ() * m_height);

	bool make_a_new_cylinder = false;

	if(px.IsEqual(vp, wxGetApp().m_geom_tol)){
		px = px.XYZ() + vshift.XYZ();
		double new_x = gp_Vec(px.XYZ()) * gp_Vec(m_pos.XDirection()) - gp_Vec(o.XYZ()) * gp_Vec(m_pos.XDirection());
		double new_y = gp_Vec(px.XYZ()) * gp_Vec(m_pos.YDirection()) - gp_Vec(o.XYZ()) * gp_Vec(m_pos.YDirection());
		make_a_new_cylinder = true;
		m_radius = sqrt(new_x * new_x + new_y * new_y);
	}
	else if(pz.IsEqual(vp, wxGetApp().m_geom_tol)){
		pz = pz.XYZ() + vshift.XYZ();
		double new_height = gp_Vec(pz.XYZ()) * gp_Vec(z_dir) - gp_Vec(o.XYZ()) * gp_Vec(z_dir);
		if(new_height > 0){
			make_a_new_cylinder = true;
			m_height = new_height;
		}
	}

	if(make_a_new_cylinder)
	{
		CCylinder* new_object = new CCylinder(m_pos, m_radius, m_height, m_title.c_str(), m_color);
		new_object->CopyIDsFrom(this);
		wxGetApp().StartHistory();
		wxGetApp().AddUndoably(new_object, NULL, NULL);
		wxGetApp().DeleteUndoably(this);
		wxGetApp().EndHistory();
		wxGetApp().m_marked_list->Clear(true);
		wxGetApp().m_marked_list->Add(new_object, true);
	}

	return true;
}

void CCylinder::SetXMLElement(TiXmlElement* element)
{
	const gp_Pnt& l = m_pos.Location();
	element->SetDoubleAttribute("lx", l.X());
	element->SetDoubleAttribute("ly", l.Y());
	element->SetDoubleAttribute("lz", l.Z());

	const gp_Dir& d = m_pos.Direction();
	element->SetDoubleAttribute("dx", d.X());
	element->SetDoubleAttribute("dy", d.Y());
	element->SetDoubleAttribute("dz", d.Z());

	const gp_Dir& x = m_pos.XDirection();
	element->SetDoubleAttribute("xx", x.X());
	element->SetDoubleAttribute("xy", x.Y());
	element->SetDoubleAttribute("xz", x.Z());

	element->SetDoubleAttribute("r", m_radius);
	element->SetDoubleAttribute("h", m_height);

	CSolid::SetXMLElement(element);
}

void CCylinder::SetFromXMLElement(TiXmlElement* pElem)
{
	// get the attributes
	double l[3] = {0, 0, 0};
	double d[3] = {0, 0, 1};
	double x[3] = {1, 0, 0};

	for(TiXmlAttribute* a = pElem->FirstAttribute(); a; a = a->Next())
	{
		std::string name(a->Name());
		if(name == "lx")	 {l[0] = a->DoubleValue();}
		else if(name == "ly"){l[1] = a->DoubleValue();}
		else if(name == "lz"){l[2] = a->DoubleValue();}

		else if(name == "dx"){d[0] = a->DoubleValue();}
		else if(name == "dy"){d[1] = a->DoubleValue();}
		else if(name == "dz"){d[2] = a->DoubleValue();}

		else if(name == "xx"){x[0] = a->DoubleValue();}
		else if(name == "xy"){x[1] = a->DoubleValue();}
		else if(name == "xz"){x[2] = a->DoubleValue();}

		else if(name == "r"){m_radius = a->DoubleValue();}
		else if(name == "h"){m_height = a->DoubleValue();}
	}

	m_pos = gp_Ax2(make_point(l), make_vector(d), make_vector(x));

	CSolid::SetFromXMLElement(pElem);
}
<|endoftext|>


<commit_before>#include "tokenizer.h"

std::string Tokenizer::charToString(char c) const
{
	std::stringstream ss;
	std::string s;
	ss << c;
	ss >> s;

	return s;
}

Tokenizer::Tokenizer()
{

}

bool Tokenizer::operator==(const Tokenizer& other) const
{
    return m_tokens == other.m_tokens;
}

std::string Tokenizer::expression() const
{
    std::string expression;

    for (auto& token : m_tokens)
        expression += token.toString() + " ";

   expression.erase(std::find_if(expression.rbegin(), expression.rend(),
                std::not1(std::ptr_fun<int, int>(isspace))).base(), expression.end());

   return expression;
}

bool Tokenizer::isEmpty() const
{
    return m_tokens.empty();
}

bool Tokenizer::isEnd() const
{
	if (isEmpty())
	{
		return true;
	}

	return m_current == m_tokens.end();
}

bool Tokenizer::tokenize(const std::string& s)
{
	bool alpha = false, error = false;
  std::string operation;

  for(auto c : s)
  {
		if(error)
		{
			break;
		}

		if(std::isspace(c))
		{
			if(!operation.empty())
			{
				append(operation);
				operation.clear();
			}

			alpha = false;
		}
		else if(std::isalpha(c))
		{
			if(!alpha && !operation.empty())
			{
				error |= append(operation);
				operation.clear();
			}

			alpha = true;
			operation += c;
		}
		else if(std::isdigit(c))
		{
			if(alpha)
			{
				operation += c;
			}
			else
			{
				operation.empty();
				error |= append(s);
			}
		}
		else
		{
			if(!operation.empty())
			{
				error |= append(operation);
				operation.clear();
			}

			alpha = false;

			error |= append(charToString(c));
		}
	}

	return !error;
}

bool Tokenizer::append(std::string operation)
{
    Token token = Token::fromString(operation);

    if(token.isError())
				return false;

    if(!m_tokens.empty())
    {
        if(m_tokens.back().append(token))
						return true;

        if(token.isDigit() && m_tokens.back().isDigit())
						return false;
    }

   m_tokens.push_back(token);

	 return true;
}

void Tokenizer::pop()
{
    if(m_tokens.empty())
        return;

    if(m_tokens.back().pop())
        return;

    m_tokens.pop_back();
}

void Tokenizer::clear()
{
    m_tokens.clear();
}

Token Tokenizer::peek() const
{
    if(m_current == m_tokens.end())
        return Token();

    return *m_current;
}

void Tokenizer::next()
{
    if(m_current == m_tokens.end())
        return;

    ++m_current;
}

void Tokenizer::reset()
{
    m_current = m_tokens.begin();
}
<commit_msg>fix bug when parsing function<commit_after>#include "tokenizer.h"

std::string Tokenizer::charToString(char c) const
{
	std::stringstream ss;
	std::string s;
	ss << c;
	ss >> s;

	return s;
}

Tokenizer::Tokenizer()
{

}

bool Tokenizer::operator==(const Tokenizer& other) const
{
    return m_tokens == other.m_tokens;
}

std::string Tokenizer::expression() const
{
    std::string expression;

    for (auto& token : m_tokens)
        expression += token.toString() + " ";

   expression.erase(std::find_if(expression.rbegin(), expression.rend(),
                std::not1(std::ptr_fun<int, int>(isspace))).base(), expression.end());

   return expression;
}

bool Tokenizer::isEmpty() const
{
    return m_tokens.empty();
}

bool Tokenizer::isEnd() const
{
	if (isEmpty())
	{
		return true;
	}

	return m_current == m_tokens.end();
}

bool Tokenizer::tokenize(const std::string& s)
{
    std::locale loc;

    bool alpha = false, error = false;
    std::string operation;

    for(auto c : s)
    {
		if(error)
		{
			break;
		}

        if(std::isspace(c, loc))
		{
			if(!operation.empty())
			{
				append(operation);
				operation.clear();
			}

			alpha = false;
		}
        else if(std::isalpha(c, loc))
		{
			if(!alpha && !operation.empty())
			{
				error |= append(operation);
				operation.clear();
			}

			alpha = true;
			operation += c;
		}
        else if(std::isdigit(c, loc))
		{
			if(alpha)
			{
				operation += c;
			}
			else
			{
				operation.empty();
				error |= append(s);
			}
		}
		else
		{
			if(!operation.empty())
			{
				error |= append(operation);
				operation.clear();
			}

			alpha = false;

			error |= append(charToString(c));
		}
	}

	return !error;
}

bool Tokenizer::append(std::string operation)
{
    Token token = Token::fromString(operation);

    if(token.isError())
				return false;

    if(!m_tokens.empty())
    {
        if(m_tokens.back().append(token))
						return true;

        if(token.isDigit() && m_tokens.back().isDigit())
						return false;
    }

   m_tokens.push_back(token);

	 return true;
}

void Tokenizer::pop()
{
    if(m_tokens.empty())
        return;

    if(m_tokens.back().pop())
        return;

    m_tokens.pop_back();
}

void Tokenizer::clear()
{
    m_tokens.clear();
}

Token Tokenizer::peek() const
{
    if(m_current == m_tokens.end())
        return Token();

    return *m_current;
}

void Tokenizer::next()
{
    if(m_current == m_tokens.end())
        return;

    ++m_current;
}

void Tokenizer::reset()
{
    m_current = m_tokens.begin();
}
<|endoftext|>


<commit_before>/// Copyright 2011 Bifrost Games. All rights reserved.
/// \author Tommy Nguyen

#include "Director.h"
#include "Physics.h"
#include "Common/Chrono.h"
#include "ConFuoco/Mixer.h"
#include "Input/Input.h"
#include "Lua/lua_Platform.h"

using Rainbow::ConFuoco::Mixer;

Director::Director()
{
	Input::Instance().set_state(this->lua.L);
}

void Director::draw()
{
	this->scenegraph.draw();
	this->lua.call("draw");
}

void Director::init(const char *const script)
{
	this->lua.load(&this->scenegraph, script);
	this->lua.call("init");
	this->lua.update();
}

void Director::set_video(const int w, const int h)
{
	Input::Instance().set_height(h);
	lua_Platform::update(this->lua.L, w, h);
}

void Director::update(const unsigned long t)
{
	Chrono::Instance().update(t);
	Mixer::Instance().update();
	Physics::Instance().step(Chrono::Instance().diff() * (1.0f / 1000.0f));
	this->lua.update();
	this->scenegraph.update();
}
<commit_msg>Deprecated draw function in Lua.<commit_after>/// Copyright 2011 Bifrost Games. All rights reserved.
/// \author Tommy Nguyen

#include "Director.h"
#include "Physics.h"
#include "Common/Chrono.h"
#include "ConFuoco/Mixer.h"
#include "Input/Input.h"
#include "Lua/lua_Platform.h"

using Rainbow::ConFuoco::Mixer;

Director::Director()
{
	Input::Instance().set_state(this->lua.L);
}

void Director::draw()
{
	this->scenegraph.draw();
}

void Director::init(const char *const script)
{
	this->lua.load(&this->scenegraph, script);
	this->lua.call("init");
	this->lua.update();
}

void Director::set_video(const int w, const int h)
{
	Input::Instance().set_height(h);
	lua_Platform::update(this->lua.L, w, h);
}

void Director::update(const unsigned long t)
{
	Chrono::Instance().update(t);
	Mixer::Instance().update();
	Physics::Instance().step(Chrono::Instance().diff() * (1.0f / 1000.0f));
	this->lua.update();
	this->scenegraph.update();
}
<|endoftext|>


<commit_before>#include "FLACFile.hpp"

using namespace std;

FLACFile::FLACFile(const string &path)
{
	m_file = new TagLib::FLAC::File(path.c_str());
}

void FLACFile::clearCover()
{
	TagLib::List<TagLib::FLAC::Picture*> embeddedPicturesList = dynamic_cast<TagLib::FLAC::File*>(m_file)->pictureList();
	TagLib::List<TagLib::FLAC::Picture*>::ConstIterator it;

	for(it = embeddedPicturesList.begin(); it !=embeddedPicturesList.end(); ++it)
	{
		TagLib::FLAC::Picture* pic = *it;
		if(pic->type() == TagLib::FLAC::Picture::Type::FrontCover)
			dynamic_cast<TagLib::FLAC::File*>(m_file)->removePicture(pic);
	}
}

void FLACFile::setCover(const TagLib::String &path)
{
	try
	{
		TagLib::List<TagLib::FLAC::Picture*> embeddedPicturesList = dynamic_cast<TagLib::FLAC::File*>(m_file)->pictureList();
		TagLib::List<TagLib::FLAC::Picture*>::ConstIterator it;

		clearCover();

		if(path != TagLib::String::null)
		{
			Cover c(path.toCString());
			TagLib::Ogg::XiphComment *t = dynamic_cast<TagLib::FLAC::File*>(m_file)->xiphComment(true);

			//Embedding picture into file
			TagLib::FLAC::Picture* picture = new TagLib::FLAC::Picture;
			picture->setData(c.data());
			picture->setType(TagLib::FLAC::Picture::Type::FrontCover);
			picture->setMimeType(c.getMimeType());
			picture->setDescription("Front Cover");
			dynamic_cast<TagLib::FLAC::File*>(m_file)->addPicture(picture);

			//Linking
			for(it = embeddedPicturesList.begin(); it != embeddedPicturesList.end(); ++it)
			{
				if((*it)->type() == TagLib::FLAC::Picture::Type::FrontCover)
				{
					TagLib::ByteVector block = (*it)->render();
					t->addField("METADATA_BLOCK_PICTURE", base64_encode(reinterpret_cast<unsigned char*>(block.data()), block.size()), true);
				}
			}
		}
	}
	catch(string &s)
	{
		cerr << s << endl;
	}
}
<commit_msg>fix segfault when overwriting FLAC tag (#3)<commit_after>#include "FLACFile.hpp"

using namespace std;

FLACFile::FLACFile(const string &path)
{
	m_file = new TagLib::FLAC::File(path.c_str());
}

void FLACFile::clearCover()
{
	dynamic_cast<TagLib::FLAC::File*>(m_file)->removePictures();
}

void FLACFile::setCover(const TagLib::String &path)
{
	TagLib::List<TagLib::FLAC::Picture*> embeddedPicturesList = dynamic_cast<TagLib::FLAC::File*>(m_file)->pictureList();
	TagLib::List<TagLib::FLAC::Picture*>::ConstIterator it;

	clearCover();

	if(path != TagLib::String::null)
	{
		Cover cover(path.toCString());

		//Embedding picture into file
		TagLib::FLAC::Picture* picture = new TagLib::FLAC::Picture;
		picture->setData(cover.data());
		picture->setType(TagLib::FLAC::Picture::Type::FrontCover);
		picture->setMimeType(cover.getMimeType());
		picture->setDescription("Front Cover");
		dynamic_cast<TagLib::FLAC::File*>(m_file)->addPicture(picture);
	}
}
<|endoftext|>


<commit_before>// Font.cc
// Copyright (c) 2002 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
//
// 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.

//$Id$

#include "StringUtil.hh"
#include "stringstream.hh"
#include "Font.hh"
#include "FontImp.hh"
#include "App.hh"

#ifdef    HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H

// for antialias
#ifdef USE_XFT
#include "XftFontImp.hh"
#endif // USE_XFT

// for multibyte support
#ifdef USE_XMB
#include "XmbFontImp.hh"
#endif //USE_XMB

// standard font system
#include "XFontImp.hh"

#include "GContext.hh"
//use gnu extensions
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif //_GNU_SOURCE

#ifndef __USE_GNU
#define __USE_GNU
#endif //__USE_GNU

#include <iostream>
#ifdef HAVE_CSTRING
  #include <cstring>
#else
  #include <string.h>
#endif
#ifdef HAVE_CSTDLIB
  #include <cstdlib>
#else
  #include <stdlib.h>
#endif
#include <list>
#include <map>
#include <typeinfo>
#include <langinfo.h>

#include <errno.h>

#ifdef HAVE_CSTDLIB
  #include <cstdlib>
#else
  #include <stdlib.h>
#endif

using namespace std;

namespace {

#ifdef HAVE_SETLOCALE
#include <locale.h>
#endif //HAVE_SETLOCALE

// use to map <font1>|<font2>|<font3> => <fontthatworks>
typedef std::map<std::string, std::string> StringMap;
typedef StringMap::iterator StringMapIt;
StringMap lookup_map;

// stores <fontthatworks and the fontimp
typedef std::map<std::string, FbTk::FontImp* > FontCache;
typedef FontCache::iterator FontCacheIt;
FontCache font_cache;

void resetEffects(FbTk::Font* font) {
    font->setHalo(false);
    font->setHaloColor(FbTk::Color("white", DefaultScreen(FbTk::App::instance()->display())));
    font->setShadow(false);
    font->setShadowColor(FbTk::Color("black", DefaultScreen(FbTk::App::instance()->display())));
    font->setShadowOffY(2);
    font->setShadowOffX(2);
}

}; // end nameless namespace

namespace FbTk {

bool Font::s_multibyte = false;
bool Font::s_utf8mode = false;

void Font::shutdown() {

    FontCacheIt fit;
    for (fit = font_cache.begin(); fit != font_cache.end(); fit++) {
        FontImp* font = fit->second;
        if (font) {
            FontCacheIt it;
            for (it = fit; it != font_cache.end(); it++)
                if (it->second == font)
                    it->second = 0;
            delete font;
        }
    }
}

Font::Font(const char *name):
    m_fontimp(0),
    m_shadow(false), m_shadow_color("black", DefaultScreen(App::instance()->display())),
    m_shadow_offx(2), m_shadow_offy(2),
    m_halo(false), m_halo_color("white", DefaultScreen(App::instance()->display()))
{
    // MB_CUR_MAX returns the size of a char in the current locale
    if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte
        s_multibyte = true;

    // check for utf-8 mode
#ifdef CODESET
    char *locale_codeset = nl_langinfo(CODESET);
#else // openbsd doesnt have this (yet?)
    char *locale_codeset = 0;
#endif // CODESET

    if (locale_codeset && strcmp("UTF-8", locale_codeset) == 0) {
        s_utf8mode = true;
    } else if (locale_codeset != 0) {
        s_utf8mode = FbStringUtil::haveUTF8();
    }

    if (name != 0) {
        load(name);
    }

}

Font::~Font() {
}

bool Font::load(const std::string &name) {

    if (name.size() == 0)
        return false;

    StringMapIt lookup_entry;
    FontCacheIt cache_entry;

    // check if one of <font1>|<font2>|<font3> is already there
    if ((lookup_entry = lookup_map.find(name)) != lookup_map.end() &&
            (cache_entry = font_cache.find(lookup_entry->second)) != font_cache.end()) {
        m_fontstr = cache_entry->first;
        m_fontimp = cache_entry->second;
        resetEffects(this);
        return true;
     }

    // split up the namelist
    typedef std::list<std::string> StringList;
    typedef StringList::iterator StringListIt;
    StringList names;
    FbTk::StringUtil::stringtok<StringList>(names, name, "|");

    StringListIt name_it;
    for (name_it = names.begin(); name_it != names.end(); name_it++) {
        FbTk::StringUtil::removeTrailingWhitespace(*name_it);
        FbTk::StringUtil::removeFirstWhitespace(*name_it);

        if ((cache_entry = font_cache.find(*name_it)) != font_cache.end()) {
            m_fontstr = cache_entry->first;
            m_fontimp = cache_entry->second;
            lookup_map[name] = m_fontstr;
            resetEffects(this);
            return true;
        }

        FontImp* tmp_font(0);

#ifdef USE_XFT
        if ((*name_it)[0] != '-')
            tmp_font = new XftFontImp(0, s_utf8mode);
#endif // USE_XFT

        if (!tmp_font) {
#ifdef USE_XMB
            if (s_multibyte || s_utf8mode)
                tmp_font = new XmbFontImp(0, s_utf8mode);
            else // basic font implementation
#endif // USE_XMB
                tmp_font = new XFontImp();
        }

        if (tmp_font && tmp_font->load((*name_it).c_str())) {
            lookup_map[name] = (*name_it);
            m_fontimp = tmp_font;
            font_cache[(*name_it)] = tmp_font;
            m_fontstr = name;
            resetEffects(this);
            return true;
        }

        delete tmp_font;
    }

    return false;
}

unsigned int Font::textWidth(const FbString &text, unsigned int size) const {
    return m_fontimp->textWidth(text, size);
}

unsigned int Font::height() const {
    return m_fontimp->height();
}

int Font::ascent() const {
    return m_fontimp->ascent();
}

int Font::descent() const {
    return m_fontimp->descent();
}

bool Font::validOrientation(FbTk::Orientation orient) {
    return m_fontimp->validOrientation(orient);
}

void Font::drawText(const FbDrawable &w, int screen, GC gc,
                    const FbString &text, size_t len, int x, int y,
                    Orientation orient) const {
    if (text.empty() || len == 0)
        return;

    // so we don't end up in a loop with m_shadow
    static bool first_run = true;

    // draw "effects" first
    if (first_run) {
        if (m_shadow) {
            FbTk::GContext shadow_gc(w);
            shadow_gc.setForeground(m_shadow_color);
            first_run = false;
            drawText(w, screen, shadow_gc.gc(), text, len,
                     x + m_shadow_offx, y + m_shadow_offy, orient);
            first_run = true;
        } else if (m_halo) {
            FbTk::GContext halo_gc(w);
            halo_gc.setForeground(m_halo_color);
            first_run = false;
            drawText(w, screen, halo_gc.gc(), text, len, x + 1, y + 1, orient);
            drawText(w, screen, halo_gc.gc(), text, len, x - 1, y + 1, orient);
            drawText(w, screen, halo_gc.gc(), text, len, x - 1, y - 1, orient);
            drawText(w, screen, halo_gc.gc(), text, len, x + 1, y - 1, orient);
            first_run = true;
        }
    }

    m_fontimp->drawText(w, screen, gc, text, len, x, y, orient);

}

};

<commit_msg>just a minor change<commit_after>// Font.cc
// Copyright (c) 2002 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
//
// 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.

//$Id$

#include "StringUtil.hh"
#include "stringstream.hh"
#include "Font.hh"
#include "FontImp.hh"
#include "App.hh"

#ifdef    HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H

// for antialias
#ifdef USE_XFT
#include "XftFontImp.hh"
#endif // USE_XFT

// for multibyte support
#ifdef USE_XMB
#include "XmbFontImp.hh"
#endif //USE_XMB

// standard font system
#include "XFontImp.hh"

#include "GContext.hh"
//use gnu extensions
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif //_GNU_SOURCE

#ifndef __USE_GNU
#define __USE_GNU
#endif //__USE_GNU

#include <iostream>
#ifdef HAVE_CSTRING
  #include <cstring>
#else
  #include <string.h>
#endif
#ifdef HAVE_CSTDLIB
  #include <cstdlib>
#else
  #include <stdlib.h>
#endif
#include <list>
#include <map>
#include <typeinfo>
#include <langinfo.h>

#include <errno.h>

#ifdef HAVE_CSTDLIB
  #include <cstdlib>
#else
  #include <stdlib.h>
#endif

using namespace std;

namespace {

#ifdef HAVE_SETLOCALE
#include <locale.h>
#endif //HAVE_SETLOCALE

// use to map <font1>|<font2>|<font3> => <fontthatworks>
typedef std::map<std::string, std::string> StringMap;
typedef StringMap::iterator StringMapIt;
StringMap lookup_map;

// stores <fontthatworks and the fontimp
typedef std::map<std::string, FbTk::FontImp* > FontCache;
typedef FontCache::iterator FontCacheIt;
FontCache font_cache;

void resetEffects(FbTk::Font& font) {
    font.setHalo(false);
    font.setHaloColor(FbTk::Color("white", DefaultScreen(FbTk::App::instance()->display())));
    font.setShadow(false);
    font.setShadowColor(FbTk::Color("black", DefaultScreen(FbTk::App::instance()->display())));
    font.setShadowOffY(2);
    font.setShadowOffX(2);
}

}; // end nameless namespace

namespace FbTk {

bool Font::s_multibyte = false;
bool Font::s_utf8mode = false;

void Font::shutdown() {

    FontCacheIt fit;
    for (fit = font_cache.begin(); fit != font_cache.end(); fit++) {
        FontImp* font = fit->second;
        if (font) {
            FontCacheIt it;
            for (it = fit; it != font_cache.end(); it++)
                if (it->second == font)
                    it->second = 0;
            delete font;
        }
    }
}

Font::Font(const char *name):
    m_fontimp(0),
    m_shadow(false), m_shadow_color("black", DefaultScreen(App::instance()->display())),
    m_shadow_offx(2), m_shadow_offy(2),
    m_halo(false), m_halo_color("white", DefaultScreen(App::instance()->display()))
{
    // MB_CUR_MAX returns the size of a char in the current locale
    if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte
        s_multibyte = true;

    // check for utf-8 mode
#ifdef CODESET
    char *locale_codeset = nl_langinfo(CODESET);
#else // openbsd doesnt have this (yet?)
    char *locale_codeset = 0;
#endif // CODESET

    if (locale_codeset && strcmp("UTF-8", locale_codeset) == 0) {
        s_utf8mode = true;
    } else if (locale_codeset != 0) {
        s_utf8mode = FbStringUtil::haveUTF8();
    }

    if (name != 0) {
        load(name);
    }

}

Font::~Font() {
}

bool Font::load(const std::string &name) {

    if (name.size() == 0)
        return false;

    StringMapIt lookup_entry;
    FontCacheIt cache_entry;

    // check if one of <font1>|<font2>|<font3> is already there
    if ((lookup_entry = lookup_map.find(name)) != lookup_map.end() &&
            (cache_entry = font_cache.find(lookup_entry->second)) != font_cache.end()) {
        m_fontstr = cache_entry->first;
        m_fontimp = cache_entry->second;
        resetEffects(*this);
        return true;
     }

    // split up the namelist
    typedef std::list<std::string> StringList;
    typedef StringList::iterator StringListIt;
    StringList names;
    FbTk::StringUtil::stringtok<StringList>(names, name, "|");

    StringListIt name_it;
    for (name_it = names.begin(); name_it != names.end(); name_it++) {
        FbTk::StringUtil::removeTrailingWhitespace(*name_it);
        FbTk::StringUtil::removeFirstWhitespace(*name_it);

        if ((cache_entry = font_cache.find(*name_it)) != font_cache.end()) {
            m_fontstr = cache_entry->first;
            m_fontimp = cache_entry->second;
            lookup_map[name] = m_fontstr;
            resetEffects(*this);
            return true;
        }

        FontImp* tmp_font(0);

#ifdef USE_XFT
        if ((*name_it)[0] != '-')
            tmp_font = new XftFontImp(0, s_utf8mode);
#endif // USE_XFT

        if (!tmp_font) {
#ifdef USE_XMB
            if (s_multibyte || s_utf8mode)
                tmp_font = new XmbFontImp(0, s_utf8mode);
            else // basic font implementation
#endif // USE_XMB
                tmp_font = new XFontImp();
        }

        if (tmp_font && tmp_font->load((*name_it).c_str())) {
            lookup_map[name] = (*name_it);
            m_fontimp = tmp_font;
            font_cache[(*name_it)] = tmp_font;
            m_fontstr = name;
            resetEffects(*this);
            return true;
        }

        delete tmp_font;
    }

    return false;
}

unsigned int Font::textWidth(const FbString &text, unsigned int size) const {
    return m_fontimp->textWidth(text, size);
}

unsigned int Font::height() const {
    return m_fontimp->height();
}

int Font::ascent() const {
    return m_fontimp->ascent();
}

int Font::descent() const {
    return m_fontimp->descent();
}

bool Font::validOrientation(FbTk::Orientation orient) {
    return m_fontimp->validOrientation(orient);
}

void Font::drawText(const FbDrawable &w, int screen, GC gc,
                    const FbString &text, size_t len, int x, int y,
                    Orientation orient) const {
    if (text.empty() || len == 0)
        return;

    // so we don't end up in a loop with m_shadow
    static bool first_run = true;

    // draw "effects" first
    if (first_run) {
        if (m_shadow) {
            FbTk::GContext shadow_gc(w);
            shadow_gc.setForeground(m_shadow_color);
            first_run = false;
            drawText(w, screen, shadow_gc.gc(), text, len,
                     x + m_shadow_offx, y + m_shadow_offy, orient);
            first_run = true;
        } else if (m_halo) {
            FbTk::GContext halo_gc(w);
            halo_gc.setForeground(m_halo_color);
            first_run = false;
            drawText(w, screen, halo_gc.gc(), text, len, x + 1, y + 1, orient);
            drawText(w, screen, halo_gc.gc(), text, len, x - 1, y + 1, orient);
            drawText(w, screen, halo_gc.gc(), text, len, x - 1, y - 1, orient);
            drawText(w, screen, halo_gc.gc(), text, len, x + 1, y - 1, orient);
            first_run = true;
        }
    }

    m_fontimp->drawText(w, screen, gc, text, len, x, y, orient);

}

};

<|endoftext|>


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

#include <new>

#include "SkPaintContext.h"

#include "SkColorPriv.h"
#include "SkShader.h"
#include "SkDashPathEffect.h"

namespace {

int RoundToInt(float x) {
  // Android uses roundf which VC doesn't have, emulate that function.
  if (fmodf(x, 1.0f) >= 0.5f)
    return (int)ceilf(x);
  return (int)floorf(x);
}

}

/*  TODO / questions

    mAlpha: how does this interact with the alpha in Color? multiply them together?
    mPorterDuffMode: do I always respect this? If so, then
                     the rgb() & 0xFF000000 check will abort drawing too often
    Is Color premultiplied or not? If it is, then I can't blindly pass it to paint.setColor()
*/
struct SkPaintContext::State {
  float               mMiterLimit;
  float               mAlpha;
  SkDrawLooper*       mLooper;
  SkPaint::Cap        mLineCap;
  SkPaint::Join       mLineJoin;
  SkPorterDuff::Mode  mPorterDuffMode;
  // Ratio of the length of a dash to its width.
  int                 mDashRatio;
  SkColor             mFillColor;
  StrokeStyle         mStrokeStyle;
  SkColor             mStrokeColor;
  float               mStrokeThickness;
  bool                mUseAntialiasing;

  SkDashPathEffect*   mDash;
  SkShader*           mGradient;
  SkShader*           mPattern;

  // Note: Keep theses default values in sync with GraphicsContextState.
  State()
      : mMiterLimit(4),
        mAlpha(1),
        mLooper(NULL),
        mLineCap(SkPaint::kDefault_Cap),
        mLineJoin(SkPaint::kDefault_Join),
        mPorterDuffMode(SkPorterDuff::kSrcOver_Mode),
        mDashRatio(3),
        mFillColor(0xFF000000),
        mStrokeStyle(SolidStroke),
        mStrokeColor(0x0FF000000),
        mStrokeThickness(0),
        mUseAntialiasing(true),
        mDash(NULL),
        mGradient(NULL),
        mPattern(NULL) {
  }

  State(const State& other) {
    other.mLooper->safeRef();
    memcpy(this, &other, sizeof(State));

    mDash->safeRef();
    mGradient->safeRef();
    mPattern->safeRef();
  }

  ~State() {
    mLooper->safeUnref();
    mDash->safeUnref();
    mGradient->safeUnref();
    mPattern->safeUnref();
  }

  SkDrawLooper* setDrawLooper(SkDrawLooper* dl) {
    SkRefCnt_SafeAssign(mLooper, dl);
    return dl;
  }

  SkColor applyAlpha(SkColor c) const {
    int s = RoundToInt(mAlpha * 256);
    if (s >= 256)
      return c;
    if (s < 0)
      return 0;

    int a = SkAlphaMul(SkColorGetA(c), s);
    return (c & 0x00FFFFFF) | (a << 24);
  }

 private:
  // Not supported yet.
  void operator=(const State&);
};

// Context will be NULL if painting should be disabled.
SkPaintContext::SkPaintContext(gfx::PlatformCanvas* context)
      : canvas_(context),
        state_stack_(sizeof(State)) {
  State* state = reinterpret_cast<State*>(state_stack_.push_back());
  new (state) State();
  state_ = state;
}

SkPaintContext::~SkPaintContext() {
  // we force restores so we don't leak any subobjects owned by our
  // stack of State records.
  while (state_stack_.count() > 0) {
    reinterpret_cast<State*>(state_stack_.back())->~State();
    state_stack_.pop_back();
  }
}

void SkPaintContext::save() {
  State* newState = reinterpret_cast<State*>(state_stack_.push_back());
  new (newState) State(*state_);
  state_ = newState;

  // Save our native canvas.
  canvas()->save();
}

void SkPaintContext::restore() {
  // Restore our native canvas.
  canvas()->restore();

  state_->~State();
  state_stack_.pop_back();

  state_ = reinterpret_cast<State*>(state_stack_.back());
}

void SkPaintContext::drawRect(SkRect rect) {
  SkPaint paint;
  int fillcolor_not_transparent = state_->mFillColor & 0xFF000000;
  if (fillcolor_not_transparent) {
    setup_paint_fill(&paint);
    canvas()->drawRect(rect, paint);
  }

  if (state_->mStrokeStyle != NoStroke && (state_->mStrokeColor & 0xFF000000)) {
    if (fillcolor_not_transparent) {
      // This call is expensive so don't call it unnecessarily.
      paint.reset();
    }
    setup_paint_stroke(&paint, &rect, 0);
    canvas()->drawRect(rect, paint);
  }
}

void SkPaintContext::setup_paint_common(SkPaint* paint) const {
#ifdef SK_DEBUGx
  {
    SkPaint defaultPaint;
    SkASSERT(*paint == defaultPaint);
  }
#endif

  paint->setAntiAlias(state_->mUseAntialiasing);
  paint->setPorterDuffXfermode(state_->mPorterDuffMode);
  paint->setLooper(state_->mLooper);

  if(state_->mGradient) {
    paint->setShader(state_->mGradient);
  } else if (state_->mPattern) {
    paint->setShader(state_->mPattern);
  }
}

void SkPaintContext::setup_paint_fill(SkPaint* paint) const {
  setup_paint_common(paint);
  paint->setColor(state_->applyAlpha(state_->mFillColor));
}

int SkPaintContext::setup_paint_stroke(SkPaint* paint,
                                       SkRect* rect,
                                       int length) {
  setup_paint_common(paint);
  float width = state_->mStrokeThickness;

  //this allows dashing and dotting to work properly for hairline strokes
  if (0 == width)
    width = 1;

  paint->setColor(state_->applyAlpha(state_->mStrokeColor));
  paint->setStyle(SkPaint::kStroke_Style);
  paint->setStrokeWidth(SkFloatToScalar(width));
  paint->setStrokeCap(state_->mLineCap);
  paint->setStrokeJoin(state_->mLineJoin);
  paint->setStrokeMiter(SkFloatToScalar(state_->mMiterLimit));

  if (rect != NULL && (RoundToInt(width) & 1)) {
    rect->inset(-SK_ScalarHalf, -SK_ScalarHalf);
  }

  if (state_->mDash) {
    paint->setPathEffect(state_->mDash);
  } else {
    switch (state_->mStrokeStyle) {
    case NoStroke:
    case SolidStroke:
      break;
    case DashedStroke:
      width = state_->mDashRatio * width;
      /* no break */
    case DottedStroke:
      SkScalar dashLength;
      if (length) {
        //determine about how many dashes or dots we should have
        int numDashes = length/RoundToInt(width);
        if (!(numDashes & 1))
          numDashes++;    //make it odd so we end on a dash/dot
        //use the number of dashes to determine the length of a dash/dot, which will be approximately width
        dashLength = SkScalarDiv(SkIntToScalar(length), SkIntToScalar(numDashes));
      } else {
        dashLength = SkFloatToScalar(width);
      }
      SkScalar intervals[2] = { dashLength, dashLength };
      paint->setPathEffect(new SkDashPathEffect(intervals, 2, 0))->unref();
    }
  }
  return RoundToInt(width);
}

SkDrawLooper* SkPaintContext::setDrawLooper(SkDrawLooper* dl) {
  return state_->setDrawLooper(dl);
}

void SkPaintContext::setMiterLimit(float ml) {
  state_->mMiterLimit = ml;
}

void SkPaintContext::setAlpha(float alpha) {
  state_->mAlpha = alpha;
}

void SkPaintContext::setLineCap(SkPaint::Cap lc) {
  state_->mLineCap = lc;
}

void SkPaintContext::setLineJoin(SkPaint::Join lj) {
  state_->mLineJoin = lj;
}

void SkPaintContext::setPorterDuffMode(SkPorterDuff::Mode pdm) {
  state_->mPorterDuffMode = pdm;
}

void SkPaintContext::setFillColor(SkColor color) {
  state_->mFillColor = color;
}

void SkPaintContext::setStrokeStyle(StrokeStyle strokestyle) {
  state_->mStrokeStyle = strokestyle;
}

void SkPaintContext::setStrokeColor(SkColor strokecolor) {
  state_->mStrokeColor = strokecolor;
}

void SkPaintContext::setStrokeThickness(float thickness) {
  state_->mStrokeThickness = thickness;
}

void SkPaintContext::setUseAntialiasing(bool enable) {
  state_->mUseAntialiasing = enable;
}

SkColor SkPaintContext::fillColor() const {
  return state_->mFillColor;
}

void SkPaintContext::beginPath() {
  path_.reset();
}

void SkPaintContext::addPath(const SkPath& path) {
  path_.addPath(path);
}

SkPath* SkPaintContext::currentPath() {
  return &path_;
}

void SkPaintContext::setFillRule(SkPath::FillType fr) {
  path_.setFillType(fr);
}

void SkPaintContext::setGradient(SkShader* gradient) {
  if (gradient != state_->mGradient) {
    state_->mGradient->safeUnref();
    state_->mGradient=gradient;
  }
}

void SkPaintContext::setPattern(SkShader* pattern) {
  if (pattern != state_->mPattern) {
    state_->mPattern->safeUnref();
    state_->mPattern=pattern;
  }
}

void SkPaintContext::setDashPathEffect(SkDashPathEffect* dash) {
  if (dash != state_->mDash) {
    state_->mDash->safeUnref();
    state_->mDash=dash;
  }
}

<commit_msg>Nevermind... re-check in 2882 (unrevert). Huanr has checked in a more promising rollback of V8.<commit_after>// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "config.h"

#include "SkPaintContext.h"

#include "SkColorPriv.h"
#include "SkShader.h"
#include "SkDashPathEffect.h"

namespace {

int RoundToInt(float x) {
  // Android uses roundf which VC doesn't have, emulate that function.
  if (fmodf(x, 1.0f) >= 0.5f)
    return (int)ceilf(x);
  return (int)floorf(x);
}

}

/*  TODO / questions

    mAlpha: how does this interact with the alpha in Color? multiply them together?
    mPorterDuffMode: do I always respect this? If so, then
                     the rgb() & 0xFF000000 check will abort drawing too often
    Is Color premultiplied or not? If it is, then I can't blindly pass it to paint.setColor()
*/
struct SkPaintContext::State {
  float               mMiterLimit;
  float               mAlpha;
  SkDrawLooper*       mLooper;
  SkPaint::Cap        mLineCap;
  SkPaint::Join       mLineJoin;
  SkPorterDuff::Mode  mPorterDuffMode;
  // Ratio of the length of a dash to its width.
  int                 mDashRatio;
  SkColor             mFillColor;
  StrokeStyle         mStrokeStyle;
  SkColor             mStrokeColor;
  float               mStrokeThickness;
  bool                mUseAntialiasing;

  SkDashPathEffect*   mDash;
  SkShader*           mGradient;
  SkShader*           mPattern;

  // Note: Keep theses default values in sync with GraphicsContextState.
  State()
      : mMiterLimit(4),
        mAlpha(1),
        mLooper(NULL),
        mLineCap(SkPaint::kDefault_Cap),
        mLineJoin(SkPaint::kDefault_Join),
        mPorterDuffMode(SkPorterDuff::kSrcOver_Mode),
        mDashRatio(3),
        mFillColor(0xFF000000),
        mStrokeStyle(SolidStroke),
        mStrokeColor(0x0FF000000),
        mStrokeThickness(0),
        mUseAntialiasing(true),
        mDash(NULL),
        mGradient(NULL),
        mPattern(NULL) {
  }

  State(const State& other) {
    other.mLooper->safeRef();
    memcpy(this, &other, sizeof(State));

    mDash->safeRef();
    mGradient->safeRef();
    mPattern->safeRef();
  }

  ~State() {
    mLooper->safeUnref();
    mDash->safeUnref();
    mGradient->safeUnref();
    mPattern->safeUnref();
  }

  SkDrawLooper* setDrawLooper(SkDrawLooper* dl) {
    SkRefCnt_SafeAssign(mLooper, dl);
    return dl;
  }

  SkColor applyAlpha(SkColor c) const {
    int s = RoundToInt(mAlpha * 256);
    if (s >= 256)
      return c;
    if (s < 0)
      return 0;

    int a = SkAlphaMul(SkColorGetA(c), s);
    return (c & 0x00FFFFFF) | (a << 24);
  }

 private:
  // Not supported yet.
  void operator=(const State&);
};

// Context will be NULL if painting should be disabled.
SkPaintContext::SkPaintContext(gfx::PlatformCanvas* context)
      : canvas_(context),
        state_stack_(sizeof(State)) {
  State* state = reinterpret_cast<State*>(state_stack_.push_back());
  new (state) State();
  state_ = state;
}

SkPaintContext::~SkPaintContext() {
  // we force restores so we don't leak any subobjects owned by our
  // stack of State records.
  while (state_stack_.count() > 0) {
    reinterpret_cast<State*>(state_stack_.back())->~State();
    state_stack_.pop_back();
  }
}

void SkPaintContext::save() {
  State* newState = reinterpret_cast<State*>(state_stack_.push_back());
  new (newState) State(*state_);
  state_ = newState;

  // Save our native canvas.
  canvas()->save();
}

void SkPaintContext::restore() {
  // Restore our native canvas.
  canvas()->restore();

  state_->~State();
  state_stack_.pop_back();

  state_ = reinterpret_cast<State*>(state_stack_.back());
}

void SkPaintContext::drawRect(SkRect rect) {
  SkPaint paint;
  int fillcolor_not_transparent = state_->mFillColor & 0xFF000000;
  if (fillcolor_not_transparent) {
    setup_paint_fill(&paint);
    canvas()->drawRect(rect, paint);
  }

  if (state_->mStrokeStyle != NoStroke && (state_->mStrokeColor & 0xFF000000)) {
    if (fillcolor_not_transparent) {
      // This call is expensive so don't call it unnecessarily.
      paint.reset();
    }
    setup_paint_stroke(&paint, &rect, 0);
    canvas()->drawRect(rect, paint);
  }
}

void SkPaintContext::setup_paint_common(SkPaint* paint) const {
#ifdef SK_DEBUGx
  {
    SkPaint defaultPaint;
    SkASSERT(*paint == defaultPaint);
  }
#endif

  paint->setAntiAlias(state_->mUseAntialiasing);
  paint->setPorterDuffXfermode(state_->mPorterDuffMode);
  paint->setLooper(state_->mLooper);

  if(state_->mGradient) {
    paint->setShader(state_->mGradient);
  } else if (state_->mPattern) {
    paint->setShader(state_->mPattern);
  }
}

void SkPaintContext::setup_paint_fill(SkPaint* paint) const {
  setup_paint_common(paint);
  paint->setColor(state_->applyAlpha(state_->mFillColor));
}

int SkPaintContext::setup_paint_stroke(SkPaint* paint,
                                       SkRect* rect,
                                       int length) {
  setup_paint_common(paint);
  float width = state_->mStrokeThickness;

  //this allows dashing and dotting to work properly for hairline strokes
  if (0 == width)
    width = 1;

  paint->setColor(state_->applyAlpha(state_->mStrokeColor));
  paint->setStyle(SkPaint::kStroke_Style);
  paint->setStrokeWidth(SkFloatToScalar(width));
  paint->setStrokeCap(state_->mLineCap);
  paint->setStrokeJoin(state_->mLineJoin);
  paint->setStrokeMiter(SkFloatToScalar(state_->mMiterLimit));

  if (rect != NULL && (RoundToInt(width) & 1)) {
    rect->inset(-SK_ScalarHalf, -SK_ScalarHalf);
  }

  if (state_->mDash) {
    paint->setPathEffect(state_->mDash);
  } else {
    switch (state_->mStrokeStyle) {
    case NoStroke:
    case SolidStroke:
      break;
    case DashedStroke:
      width = state_->mDashRatio * width;
      /* no break */
    case DottedStroke:
      SkScalar dashLength;
      if (length) {
        //determine about how many dashes or dots we should have
        int numDashes = length/RoundToInt(width);
        if (!(numDashes & 1))
          numDashes++;    //make it odd so we end on a dash/dot
        //use the number of dashes to determine the length of a dash/dot, which will be approximately width
        dashLength = SkScalarDiv(SkIntToScalar(length), SkIntToScalar(numDashes));
      } else {
        dashLength = SkFloatToScalar(width);
      }
      SkScalar intervals[2] = { dashLength, dashLength };
      paint->setPathEffect(new SkDashPathEffect(intervals, 2, 0))->unref();
    }
  }
  return RoundToInt(width);
}

SkDrawLooper* SkPaintContext::setDrawLooper(SkDrawLooper* dl) {
  return state_->setDrawLooper(dl);
}

void SkPaintContext::setMiterLimit(float ml) {
  state_->mMiterLimit = ml;
}

void SkPaintContext::setAlpha(float alpha) {
  state_->mAlpha = alpha;
}

void SkPaintContext::setLineCap(SkPaint::Cap lc) {
  state_->mLineCap = lc;
}

void SkPaintContext::setLineJoin(SkPaint::Join lj) {
  state_->mLineJoin = lj;
}

void SkPaintContext::setPorterDuffMode(SkPorterDuff::Mode pdm) {
  state_->mPorterDuffMode = pdm;
}

void SkPaintContext::setFillColor(SkColor color) {
  state_->mFillColor = color;
}

void SkPaintContext::setStrokeStyle(StrokeStyle strokestyle) {
  state_->mStrokeStyle = strokestyle;
}

void SkPaintContext::setStrokeColor(SkColor strokecolor) {
  state_->mStrokeColor = strokecolor;
}

void SkPaintContext::setStrokeThickness(float thickness) {
  state_->mStrokeThickness = thickness;
}

void SkPaintContext::setUseAntialiasing(bool enable) {
  state_->mUseAntialiasing = enable;
}

SkColor SkPaintContext::fillColor() const {
  return state_->mFillColor;
}

void SkPaintContext::beginPath() {
  path_.reset();
}

void SkPaintContext::addPath(const SkPath& path) {
  path_.addPath(path);
}

SkPath* SkPaintContext::currentPath() {
  return &path_;
}

void SkPaintContext::setFillRule(SkPath::FillType fr) {
  path_.setFillType(fr);
}

void SkPaintContext::setGradient(SkShader* gradient) {
  if (gradient != state_->mGradient) {
    state_->mGradient->safeUnref();
    state_->mGradient=gradient;
  }
}

void SkPaintContext::setPattern(SkShader* pattern) {
  if (pattern != state_->mPattern) {
    state_->mPattern->safeUnref();
    state_->mPattern=pattern;
  }
}

void SkPaintContext::setDashPathEffect(SkDashPathEffect* dash) {
  if (dash != state_->mDash) {
    state_->mDash->safeUnref();
    state_->mDash=dash;
  }
}

<|endoftext|>


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

#include "platform/platform.h"
#include "materials/materialList.h"

#include "materials/matInstance.h"
#include "materials/materialManager.h"
#include "materials/materialFeatureTypes.h"
#include "materials/processedMaterial.h"
#include "core/volume.h"
#include "console/simSet.h"

MaterialList::MaterialList()
{
   VECTOR_SET_ASSOCIATION(mMatInstList);
   VECTOR_SET_ASSOCIATION(mMaterialNames);
}

MaterialList::MaterialList(const MaterialList* pCopy)
{
   VECTOR_SET_ASSOCIATION(mMatInstList);
   VECTOR_SET_ASSOCIATION(mMaterialNames);

   mMaterialNames.setSize(pCopy->mMaterialNames.size());
   S32 i;
   for (i = 0; i < mMaterialNames.size(); i++)
   {
      mMaterialNames[i] = pCopy->mMaterialNames[i];
   }

   clearMatInstList();
   mMatInstList.setSize(pCopy->size());
   for( i = 0; i < mMatInstList.size(); i++ )
   {
      if( i < pCopy->mMatInstList.size() && pCopy->mMatInstList[i] )
      {
         mMatInstList[i] = pCopy->mMatInstList[i]->getMaterial()->createMatInstance();
      }
      else
      {
         mMatInstList[i] = NULL;
      }
   }
}

MaterialList::MaterialList(U32 materialCount, const char **materialNames)
{
   VECTOR_SET_ASSOCIATION(mMaterialNames);

   set(materialCount, materialNames);
}

//--------------------------------------
void MaterialList::set(U32 materialCount, const char **materialNames)
{
   free();
   mMaterialNames.setSize(materialCount);
   clearMatInstList();
   mMatInstList.setSize(materialCount);
   for(U32 i = 0; i < materialCount; i++)
   {
      mMaterialNames[i] = materialNames[i];
      mMatInstList[i] = NULL;
   }
}

//--------------------------------------
MaterialList::~MaterialList()
{
   free();
}

//--------------------------------------
void MaterialList::setMaterialName(U32 index, const String& name)
{
   if (index < mMaterialNames.size())
      mMaterialNames[index] = name;
}

//--------------------------------------
GFXTextureObject *MaterialList::getDiffuseTexture(U32 index)
{
   AssertFatal(index < (U32) mMatInstList.size(), "MaterialList::getDiffuseTex: index lookup out of range.");

   MatInstance *matInst = dynamic_cast<MatInstance*>(mMatInstList[index]);
   if (matInst && matInst->getProcessedMaterial())
      return matInst->getProcessedMaterial()->getStageTexture(0, MFT_DiffuseMap);
   else
      return NULL;
}

//--------------------------------------
void MaterialList::free()
{
   clearMatInstList();
   mMatInstList.clear();
   mMaterialNames.clear();
}

/*
//--------------------------------------
U32 MaterialList::push_back(GFXTexHandle textureHandle, const String &filename)
{
   mMaterialNames.push_back(filename);
   mMatInstList.push_back(NULL);

   // return the index
   return mMaterialNames.size()-1;
}
*/

//--------------------------------------
U32 MaterialList::push_back(const String &filename, Material* material)
{
   mMaterialNames.push_back(filename);
   mMatInstList.push_back(material ? material->createMatInstance() : NULL);

   // return the index
   return mMaterialNames.size()-1;
}

//--------------------------------------
bool MaterialList::read(Stream &stream)
{
   free();

   // check the stream version
   U8 version;
   if ( stream.read(&version) && version != BINARY_FILE_VERSION)
      return readText(stream,version);

   // how many materials?
   U32 count;
   if ( !stream.read(&count) )
      return false;

   // pre-size the vectors for efficiency
   mMaterialNames.reserve(count);

   // read in the materials
   for (U32 i=0; i<count; i++)
   {
      // Load the bitmap name
      char buffer[256];
      stream.readString(buffer);
      if( !buffer[0] )
      {
         AssertWarn(0, "MaterialList::read: error reading stream");
         return false;
      }

      // Material paths are a legacy of Tribes tools,
      // strip them off...
      char *name = &buffer[dStrlen(buffer)];
      while (name != buffer && name[-1] != '/' && name[-1] != '\\')
         name--;

      // Add it to the list
      mMaterialNames.push_back(name);
      mMatInstList.push_back(NULL);
   }

   return (stream.getStatus() == Stream::Ok);
}

//--------------------------------------
bool MaterialList::write(Stream &stream)
{
   stream.write((U8)BINARY_FILE_VERSION);          // version
   stream.write((U32)mMaterialNames.size());       // material count

   for(S32 i=0; i < mMaterialNames.size(); i++)    // material names
      stream.writeString(mMaterialNames[i]);

   return (stream.getStatus() == Stream::Ok);
}

//--------------------------------------
bool MaterialList::readText(Stream &stream, U8 firstByte)
{
   free();

   if (!firstByte)
      return (stream.getStatus() == Stream::Ok || stream.getStatus() == Stream::EOS);

   char buf[1024];
   buf[0] = firstByte;
   U32 offset = 1;

   for(;;)
   {
      stream.readLine((U8*)(buf+offset), sizeof(buf)-offset);
      if(!buf[0])
         break;
      offset = 0;

      // Material paths are a legacy of Tribes tools,
      // strip them off...
      char *name = &buf[dStrlen(buf)];
      while (name != buf && name[-1] != '/' && name[-1] != '\\')
         name--;

      // Add it to the list
      mMaterialNames.push_back(name);
      mMatInstList.push_back(NULL);
   }

   return (stream.getStatus() == Stream::Ok || stream.getStatus() == Stream::EOS);
}

bool MaterialList::readText(Stream &stream)
{
   U8 firstByte;
   stream.read(&firstByte);
   return readText(stream,firstByte);
}

//--------------------------------------
bool MaterialList::writeText(Stream &stream)
{
   for(S32 i=0; i < mMaterialNames.size(); i++)
      stream.writeLine((U8*)(mMaterialNames[i].c_str()));
   stream.writeLine((U8*)"");

   return (stream.getStatus() == Stream::Ok);
}

//--------------------------------------------------------------------------
// Clear all materials in the mMatInstList member variable
//--------------------------------------------------------------------------
void MaterialList::clearMatInstList()
{
   // clear out old materials.  any non null element of the list should be pointing at deletable memory,
   // although multiple indexes may be pointing at the same memory so we have to be careful (see
   // comment in loop body)
   for (U32 i=0; i<mMatInstList.size(); i++)
   {
      if (mMatInstList[i])
      {
         BaseMatInstance* current = mMatInstList[i];
         delete current;
         mMatInstList[i] = NULL;

         // ok, since ts material lists can remap difference indexes to the same object
         // we need to make sure that we don't delete the same memory twice.  walk the
         // rest of the list and null out any pointers that match the one we deleted.
         for (U32 j=0; j<mMatInstList.size(); j++)
            if (mMatInstList[j] == current)
               mMatInstList[j] = NULL;
      }
   }
}

//--------------------------------------------------------------------------
// Map materials - map materials to the textures in the list
//--------------------------------------------------------------------------
void MaterialList::mapMaterials()
{
   mMatInstList.setSize( mMaterialNames.size() );

   for( U32 i=0; i<mMaterialNames.size(); i++ )
      mapMaterial( i );
}

/// Map the material name at the given index to a material instance.
///
/// @note The material instance that is created will not be initialized.

void MaterialList::mapMaterial( U32 i )
{
   AssertFatal( i < size(), "MaterialList::mapMaterialList - index out of bounds" );

   if( mMatInstList[i] != NULL )
      return;

   // lookup a material property entry
   const String &matName = getMaterialName(i);

   // JMQ: this code assumes that all materials have names.
   if( matName.isEmpty() )
   {
      mMatInstList[i] = NULL;
      return;
   }

   String materialName = MATMGR->getMapEntry(matName);

   // IF we didn't find it, then look for a PolyStatic generated Material
   //  [a little cheesy, but we need to allow for user override of generated Materials]
   if ( materialName.isEmpty() )
      materialName = MATMGR->getMapEntry( String::ToString( "polyMat_%s", matName.c_str() ) );

   if ( materialName.isNotEmpty() )
   {
      Material * mat = MATMGR->getMaterialDefinitionByName( materialName );
      mMatInstList[i] = mat ? mat->createMatInstance() : MATMGR->createWarningMatInstance();
   }
   else
   {
      if ( Con::getBoolVariable( "$Materials::createMissing", true ) )
      {
         // No Material found, create new "default" material with just a diffuseMap

         // First see if there is a valid diffuse texture
         GFXTexHandle texHandle;
         if (mLookupPath.isEmpty())
         {
            texHandle.set( mMaterialNames[i], &GFXDefaultStaticDiffuseProfile, avar("%s() - handle (line %d)", __FUNCTION__, __LINE__) );
         }
         else
         {
            // Should we strip off the extension of the path here before trying
            // to load the texture?
            String fullPath = String::ToString( "%s/%s", mLookupPath.c_str(), mMaterialNames[i].c_str() );
            texHandle.set( fullPath, &GFXDefaultStaticDiffuseProfile, avar("%s() - handle (line %d)", __FUNCTION__, __LINE__) );
         }

         if ( texHandle.isValid() )
         {
            String newMatName = Sim::getUniqueName( "DefaultMaterial" );
            Material *newMat = MATMGR->allocateAndRegister( newMatName, mMaterialNames[i] );

            // Flag this as an autogenerated Material
            newMat->mAutoGenerated = true;

            // Overwrite diffuseMap in new material
            newMat->mDiffuseMapFilename[0] = texHandle->mTextureLookupName;

            // Set up some defaults for transparent textures
            if (texHandle->mHasTransparency)
            {
               newMat->mTranslucent = true;
               newMat->mTranslucentBlendOp = Material::LerpAlpha;
               newMat->mTranslucentZWrite = true;
               newMat->mAlphaRef = 20;
            }

            // create a MatInstance for the new material
            mMatInstList[i] = newMat->createMatInstance();

            #ifndef TORQUE_SHIPPING
               Con::warnf( "[MaterialList::mapMaterials] Creating missing material for texture: %s", texHandle->mTextureLookupName.c_str() );
            #endif
         }
         else
         {
            Con::errorf( "[MaterialList::mapMaterials] Unable to find material for texture: %s", mMaterialNames[i].c_str() );
            mMatInstList[i] = MATMGR->createWarningMatInstance();
         }
      }
      else
      {
         mMatInstList[i] = MATMGR->createWarningMatInstance();
      }
   }
}

void MaterialList::initMatInstances(   const FeatureSet &features,
                                       const GFXVertexFormat *vertexFormat )
{
   for( U32 i=0; i < mMatInstList.size(); i++ )
   {
      BaseMatInstance *matInst = mMatInstList[i];
      if ( !matInst )
         continue;

      if ( !matInst->init( features, vertexFormat ) )
      {
         Con::errorf( "MaterialList::initMatInstances - failed to initialize material instance for '%s'",
            matInst->getMaterial()->getName() );

         // Fall back to warning material.

         SAFE_DELETE( matInst );
         matInst = MATMGR->createMatInstance( "WarningMaterial" );
         matInst->init( MATMGR->getDefaultFeatures(), vertexFormat );
         mMatInstList[ i ] = matInst;
      }
   }

}

void MaterialList::setMaterialInst( BaseMatInstance *matInst, U32 texIndex )
{
   AssertFatal( texIndex < mMatInstList.size(), "MaterialList::setMaterialInst - index out of bounds" );
   mMatInstList[texIndex] = matInst;
}
<commit_msg>Fix use-after-delete<commit_after>//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include "platform/platform.h"
#include "materials/materialList.h"

#include "materials/matInstance.h"
#include "materials/materialManager.h"
#include "materials/materialFeatureTypes.h"
#include "materials/processedMaterial.h"
#include "core/volume.h"
#include "console/simSet.h"

MaterialList::MaterialList()
{
   VECTOR_SET_ASSOCIATION(mMatInstList);
   VECTOR_SET_ASSOCIATION(mMaterialNames);
}

MaterialList::MaterialList(const MaterialList* pCopy)
{
   VECTOR_SET_ASSOCIATION(mMatInstList);
   VECTOR_SET_ASSOCIATION(mMaterialNames);

   mMaterialNames.setSize(pCopy->mMaterialNames.size());
   S32 i;
   for (i = 0; i < mMaterialNames.size(); i++)
   {
      mMaterialNames[i] = pCopy->mMaterialNames[i];
   }

   clearMatInstList();
   mMatInstList.setSize(pCopy->size());
   for( i = 0; i < mMatInstList.size(); i++ )
   {
      if( i < pCopy->mMatInstList.size() && pCopy->mMatInstList[i] )
      {
         mMatInstList[i] = pCopy->mMatInstList[i]->getMaterial()->createMatInstance();
      }
      else
      {
         mMatInstList[i] = NULL;
      }
   }
}

MaterialList::MaterialList(U32 materialCount, const char **materialNames)
{
   VECTOR_SET_ASSOCIATION(mMaterialNames);

   set(materialCount, materialNames);
}

//--------------------------------------
void MaterialList::set(U32 materialCount, const char **materialNames)
{
   free();
   mMaterialNames.setSize(materialCount);
   clearMatInstList();
   mMatInstList.setSize(materialCount);
   for(U32 i = 0; i < materialCount; i++)
   {
      mMaterialNames[i] = materialNames[i];
      mMatInstList[i] = NULL;
   }
}

//--------------------------------------
MaterialList::~MaterialList()
{
   free();
}

//--------------------------------------
void MaterialList::setMaterialName(U32 index, const String& name)
{
   if (index < mMaterialNames.size())
      mMaterialNames[index] = name;
}

//--------------------------------------
GFXTextureObject *MaterialList::getDiffuseTexture(U32 index)
{
   AssertFatal(index < (U32) mMatInstList.size(), "MaterialList::getDiffuseTex: index lookup out of range.");

   MatInstance *matInst = dynamic_cast<MatInstance*>(mMatInstList[index]);
   if (matInst && matInst->getProcessedMaterial())
      return matInst->getProcessedMaterial()->getStageTexture(0, MFT_DiffuseMap);
   else
      return NULL;
}

//--------------------------------------
void MaterialList::free()
{
   clearMatInstList();
   mMatInstList.clear();
   mMaterialNames.clear();
}

/*
//--------------------------------------
U32 MaterialList::push_back(GFXTexHandle textureHandle, const String &filename)
{
   mMaterialNames.push_back(filename);
   mMatInstList.push_back(NULL);

   // return the index
   return mMaterialNames.size()-1;
}
*/

//--------------------------------------
U32 MaterialList::push_back(const String &filename, Material* material)
{
   mMaterialNames.push_back(filename);
   mMatInstList.push_back(material ? material->createMatInstance() : NULL);

   // return the index
   return mMaterialNames.size()-1;
}

//--------------------------------------
bool MaterialList::read(Stream &stream)
{
   free();

   // check the stream version
   U8 version;
   if ( stream.read(&version) && version != BINARY_FILE_VERSION)
      return readText(stream,version);

   // how many materials?
   U32 count;
   if ( !stream.read(&count) )
      return false;

   // pre-size the vectors for efficiency
   mMaterialNames.reserve(count);

   // read in the materials
   for (U32 i=0; i<count; i++)
   {
      // Load the bitmap name
      char buffer[256];
      stream.readString(buffer);
      if( !buffer[0] )
      {
         AssertWarn(0, "MaterialList::read: error reading stream");
         return false;
      }

      // Material paths are a legacy of Tribes tools,
      // strip them off...
      char *name = &buffer[dStrlen(buffer)];
      while (name != buffer && name[-1] != '/' && name[-1] != '\\')
         name--;

      // Add it to the list
      mMaterialNames.push_back(name);
      mMatInstList.push_back(NULL);
   }

   return (stream.getStatus() == Stream::Ok);
}

//--------------------------------------
bool MaterialList::write(Stream &stream)
{
   stream.write((U8)BINARY_FILE_VERSION);          // version
   stream.write((U32)mMaterialNames.size());       // material count

   for(S32 i=0; i < mMaterialNames.size(); i++)    // material names
      stream.writeString(mMaterialNames[i]);

   return (stream.getStatus() == Stream::Ok);
}

//--------------------------------------
bool MaterialList::readText(Stream &stream, U8 firstByte)
{
   free();

   if (!firstByte)
      return (stream.getStatus() == Stream::Ok || stream.getStatus() == Stream::EOS);

   char buf[1024];
   buf[0] = firstByte;
   U32 offset = 1;

   for(;;)
   {
      stream.readLine((U8*)(buf+offset), sizeof(buf)-offset);
      if(!buf[0])
         break;
      offset = 0;

      // Material paths are a legacy of Tribes tools,
      // strip them off...
      char *name = &buf[dStrlen(buf)];
      while (name != buf && name[-1] != '/' && name[-1] != '\\')
         name--;

      // Add it to the list
      mMaterialNames.push_back(name);
      mMatInstList.push_back(NULL);
   }

   return (stream.getStatus() == Stream::Ok || stream.getStatus() == Stream::EOS);
}

bool MaterialList::readText(Stream &stream)
{
   U8 firstByte;
   stream.read(&firstByte);
   return readText(stream,firstByte);
}

//--------------------------------------
bool MaterialList::writeText(Stream &stream)
{
   for(S32 i=0; i < mMaterialNames.size(); i++)
      stream.writeLine((U8*)(mMaterialNames[i].c_str()));
   stream.writeLine((U8*)"");

   return (stream.getStatus() == Stream::Ok);
}

//--------------------------------------------------------------------------
// Clear all materials in the mMatInstList member variable
//--------------------------------------------------------------------------
void MaterialList::clearMatInstList()
{
   // clear out old materials.  any non null element of the list should be pointing at deletable memory,
   // although multiple indexes may be pointing at the same memory so we have to be careful (see
   // comment in loop body)
   for (U32 i=0; i<mMatInstList.size(); i++)
   {
      if (mMatInstList[i])
      {
         BaseMatInstance* current = mMatInstList[i];

         // ok, since ts material lists can remap difference indexes to the same object
         // we need to make sure that we don't delete the same memory twice.  walk the
         // rest of the list and null out any pointers that match the one we deleted.
         for (U32 j=0; j<mMatInstList.size(); j++)
            if (mMatInstList[j] == current)
               mMatInstList[j] = NULL;

         mMatInstList[i] = NULL;
         delete current;
      }
   }
}

//--------------------------------------------------------------------------
// Map materials - map materials to the textures in the list
//--------------------------------------------------------------------------
void MaterialList::mapMaterials()
{
   mMatInstList.setSize( mMaterialNames.size() );

   for( U32 i=0; i<mMaterialNames.size(); i++ )
      mapMaterial( i );
}

/// Map the material name at the given index to a material instance.
///
/// @note The material instance that is created will not be initialized.

void MaterialList::mapMaterial( U32 i )
{
   AssertFatal( i < size(), "MaterialList::mapMaterialList - index out of bounds" );

   if( mMatInstList[i] != NULL )
      return;

   // lookup a material property entry
   const String &matName = getMaterialName(i);

   // JMQ: this code assumes that all materials have names.
   if( matName.isEmpty() )
   {
      mMatInstList[i] = NULL;
      return;
   }

   String materialName = MATMGR->getMapEntry(matName);

   // IF we didn't find it, then look for a PolyStatic generated Material
   //  [a little cheesy, but we need to allow for user override of generated Materials]
   if ( materialName.isEmpty() )
      materialName = MATMGR->getMapEntry( String::ToString( "polyMat_%s", matName.c_str() ) );

   if ( materialName.isNotEmpty() )
   {
      Material * mat = MATMGR->getMaterialDefinitionByName( materialName );
      mMatInstList[i] = mat ? mat->createMatInstance() : MATMGR->createWarningMatInstance();
   }
   else
   {
      if ( Con::getBoolVariable( "$Materials::createMissing", true ) )
      {
         // No Material found, create new "default" material with just a diffuseMap

         // First see if there is a valid diffuse texture
         GFXTexHandle texHandle;
         if (mLookupPath.isEmpty())
         {
            texHandle.set( mMaterialNames[i], &GFXDefaultStaticDiffuseProfile, avar("%s() - handle (line %d)", __FUNCTION__, __LINE__) );
         }
         else
         {
            // Should we strip off the extension of the path here before trying
            // to load the texture?
            String fullPath = String::ToString( "%s/%s", mLookupPath.c_str(), mMaterialNames[i].c_str() );
            texHandle.set( fullPath, &GFXDefaultStaticDiffuseProfile, avar("%s() - handle (line %d)", __FUNCTION__, __LINE__) );
         }

         if ( texHandle.isValid() )
         {
            String newMatName = Sim::getUniqueName( "DefaultMaterial" );
            Material *newMat = MATMGR->allocateAndRegister( newMatName, mMaterialNames[i] );

            // Flag this as an autogenerated Material
            newMat->mAutoGenerated = true;

            // Overwrite diffuseMap in new material
            newMat->mDiffuseMapFilename[0] = texHandle->mTextureLookupName;

            // Set up some defaults for transparent textures
            if (texHandle->mHasTransparency)
            {
               newMat->mTranslucent = true;
               newMat->mTranslucentBlendOp = Material::LerpAlpha;
               newMat->mTranslucentZWrite = true;
               newMat->mAlphaRef = 20;
            }

            // create a MatInstance for the new material
            mMatInstList[i] = newMat->createMatInstance();

            #ifndef TORQUE_SHIPPING
               Con::warnf( "[MaterialList::mapMaterials] Creating missing material for texture: %s", texHandle->mTextureLookupName.c_str() );
            #endif
         }
         else
         {
            Con::errorf( "[MaterialList::mapMaterials] Unable to find material for texture: %s", mMaterialNames[i].c_str() );
            mMatInstList[i] = MATMGR->createWarningMatInstance();
         }
      }
      else
      {
         mMatInstList[i] = MATMGR->createWarningMatInstance();
      }
   }
}

void MaterialList::initMatInstances(   const FeatureSet &features,
                                       const GFXVertexFormat *vertexFormat )
{
   for( U32 i=0; i < mMatInstList.size(); i++ )
   {
      BaseMatInstance *matInst = mMatInstList[i];
      if ( !matInst )
         continue;

      if ( !matInst->init( features, vertexFormat ) )
      {
         Con::errorf( "MaterialList::initMatInstances - failed to initialize material instance for '%s'",
            matInst->getMaterial()->getName() );

         // Fall back to warning material.

         SAFE_DELETE( matInst );
         matInst = MATMGR->createMatInstance( "WarningMaterial" );
         matInst->init( MATMGR->getDefaultFeatures(), vertexFormat );
         mMatInstList[ i ] = matInst;
      }
   }

}

void MaterialList::setMaterialInst( BaseMatInstance *matInst, U32 texIndex )
{
   AssertFatal( texIndex < mMatInstList.size(), "MaterialList::setMaterialInst - index out of bounds" );
   mMatInstList[texIndex] = matInst;
}
<|endoftext|>