<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
// Class header file...
#include "XObjectFactoryDefault.hpp"

#include <algorithm>
#include <memory>

#include "XBoolean.hpp"
#include "XNodeSet.hpp"
#include "XNull.hpp"
#include "XNumber.hpp"
#include "XResultTreeFrag.hpp"
#include "XSpan.hpp"
#include "XString.hpp"
#include "XStringAdapter.hpp"
#include "XStringCached.hpp"
#include "XStringReference.hpp"
#include "XUnknown.hpp"

XObjectFactoryDefault::XObjectFactoryDefault(
			unsigned int	theXStringBlockSize,
			unsigned int	theXNumberBlockSize,
			unsigned int	theXNodeSetBlockSize,
			unsigned int	theXResultTreeFragBlockSize) :
	XObjectFactory(),
	m_xstringAdapterAllocator(theXStringBlockSize),
	m_xstringAllocator(theXStringBlockSize),
	m_xstringCachedAllocator(theXStringBlockSize),
	m_xstringReferenceAllocator(theXStringBlockSize),
	m_xnumberAllocator(theXNumberBlockSize),
	m_xnodesetAllocator(theXNodeSetBlockSize),
	m_xresultTreeFragAllocator(theXResultTreeFragBlockSize),
	m_xtokenNumberAdapterAllocator(theXNumberBlockSize),
	m_xtokenStringAdapterAllocator(theXStringBlockSize),
	m_xobjects(),
	m_xnumberCache(),
	m_xnodesetCache(),
	m_xresultTreeFragCache(),
	m_XNull(new XNull),
	m_xbooleanFalse(new XBoolean(false)),
	m_xbooleanTrue(new XBoolean(true))
{
}

XObjectFactoryDefault::~XObjectFactoryDefault()
{
	reset();
}

bool
XObjectFactoryDefault::doReturnObject(
			XObject*	theXObject,
			bool		fInReset)
{
	assert(theXObject != 0);

	bool bStatus = false;

	const XObject::eObjectType	theType = getRealType(*theXObject);

	switch(theType)
	{
	case XObject::eTypeBoolean:
	case XObject::eTypeNull:
		{
			bStatus = true;
		}

	case XObject::eTypeStringAdapter:
		{
			XStringAdapter* const		theXStringAdapter =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XStringAdapter*)theXObject;
#else
				static_cast<XStringAdapter*>(theXObject);
#endif

			bStatus = m_xstringAdapterAllocator.destroy(theXStringAdapter);
		}
		break;

	case XObject::eTypeXTokenNumberAdapter:
		{
			XTokenNumberAdapter* const	theAdapter =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XTokenNumberAdapter*)theXObject;
#else
				static_cast<XTokenNumberAdapter*>(theXObject);
#endif

			bStatus = m_xtokenNumberAdapterAllocator.destroy(theAdapter);
		}
		break;

	case XObject::eTypeXTokenStringAdapter:
		{
			XTokenStringAdapter* const	theAdapter =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XTokenStringAdapter*)theXObject;
#else
				static_cast<XTokenStringAdapter*>(theXObject);
#endif

			bStatus = m_xtokenStringAdapterAllocator.destroy(theAdapter);
		}
		break;

	case XObject::eTypeString:
		{
			XString* const	theXString =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XString*)theXObject;
#else
				static_cast<XString*>(theXObject);
#endif

			bStatus = m_xstringAllocator.destroy(theXString);
		}
		break;

	case XObject::eTypeStringCached:
		{
			XStringCached* const	theXStringCached =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XStringCached*)theXObject;
#else
				static_cast<XStringCached*>(theXObject);
#endif

			bStatus = m_xstringCachedAllocator.destroy(theXStringCached);
		}
		break;

	case XObject::eTypeStringReference:
		{
			XStringReference* const		theXStringReference =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XStringReference*)theXObject;
#else
				static_cast<XStringReference*>(theXObject);
#endif

			bStatus = m_xstringReferenceAllocator.destroy(theXStringReference);
		}
		break;

	case  XObject::eTypeNumber:
		{
			XNumber* const	theXNumber =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XNumber*)theXObject;
#else
				static_cast<XNumber*>(theXObject);
#endif

			if (m_xnumberCache.size() < eXNumberCacheMax)
			{
				m_xnumberCache.push_back(theXNumber);

				bStatus = true;
			}
			else
			{
				bStatus = m_xnumberAllocator.destroy(theXNumber);
			}
		}
		break;

	case XObject::eTypeNodeSet:
		{
			XNodeSet* const		theXNodeSet =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XNodeSet*)theXObject;
#else
				static_cast<XNodeSet*>(theXObject);
#endif

			if (m_xnodesetCache.size() < eXNodeSetCacheMax)
			{
				theXNodeSet->release();

				m_xnodesetCache.push_back(theXNodeSet);

				bStatus = true;
			}
			else
			{
				bStatus = m_xnodesetAllocator.destroy(theXNodeSet);
			}
		}
		break;

	case XObject::eTypeResultTreeFrag:
		{
			XResultTreeFrag* const	theXResultTreeFrag =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XResultTreeFrag*)theXObject;
#else
				static_cast<XResultTreeFrag*>(theXObject);
#endif

			if (m_xresultTreeFragCache.size() < eXResultTreeFragCacheMax)
			{
				m_xresultTreeFragCache.push_back(theXResultTreeFrag);

				bStatus = true;
			}
			else
			{
				bStatus = m_xresultTreeFragAllocator.destroy(theXResultTreeFrag);
			}
		}
		break;

	default:
		{
#if !defined(XALAN_NO_NAMESPACES)
			using std::find;
#endif

			const XObjectCollectionType::iterator	i =
					find(m_xobjects.begin(), m_xobjects.end(), theXObject);

			if (i != m_xobjects.end())
			{
				if (fInReset == false)
				{
					m_xobjects.erase(i);
				}

				deleteObject(theXObject);

				bStatus = true;
			}
		}
		break;
	}

	return bStatus;
}

const XObjectPtr
XObjectFactoryDefault::createBoolean(
			bool	theValue)
{
	if (theValue == true)
	{
		return XObjectPtr(m_xbooleanTrue.get());
	}
	else
	{
		return XObjectPtr(m_xbooleanFalse.get());
	}
}

const XObjectPtr
XObjectFactoryDefault::createNull()
{
	return XObjectPtr(m_XNull.get());
}

const XObjectPtr
XObjectFactoryDefault::createUnknown(const XalanDOMString&	theValue)
{
	XUnknown* const	theXUnknown = new XUnknown(theValue);

	m_xobjects.push_back(theXUnknown);

	theXUnknown->setFactory(this);

	return XObjectPtr(theXUnknown);
}

const XObjectPtr
XObjectFactoryDefault::createSpan(BorrowReturnMutableNodeRefList&	theValue)
{
	XSpan* const	theXObject = new XSpan(theValue);

	m_xobjects.push_back(theXObject);

	theXObject->setFactory(this);

	return XObjectPtr(theXObject);
}

const XObjectPtr
XObjectFactoryDefault::createNumber(double	theValue)
{
	if (m_xnumberCache.size() > 0)
	{
		XNumber* const	theXNumber = m_xnumberCache.back();

		m_xnumberCache.pop_back();

		theXNumber->set(theValue);

		return XObjectPtr(theXNumber);
	}
	else
	{
		m_xnumberCache.reserve(eXNumberCacheMax);

		XObject* const	theXObject = m_xnumberAllocator.createNumber(theValue);

		theXObject->setFactory(this);

		return XObjectPtr(theXObject);
	}
}

const XObjectPtr
XObjectFactoryDefault::createNumber(const XToken&	theValue)
{
	XObject*	theXObject = m_xtokenNumberAdapterAllocator.create(theValue);

	theXObject->setFactory(this);

	return XObjectPtr(theXObject);
}

const XObjectPtr
XObjectFactoryDefault::createNodeSet(BorrowReturnMutableNodeRefList&	theValue)
{
	if (m_xnodesetCache.size() > 0)
	{
		XNodeSet* const		theXObject = m_xnodesetCache.back();

		m_xnodesetCache.pop_back();

		theXObject->set(theValue);

		return XObjectPtr(theXObject);
	}
	else
	{
		m_xnodesetCache.reserve(eXNodeSetCacheMax);

		XNodeSet* const		theXObject = m_xnodesetAllocator.createNodeSet(theValue);

		theXObject->setFactory(this);

		return XObjectPtr(theXObject);
	}
}

const XObjectPtr
XObjectFactoryDefault::createString(const XalanDOMString&	theValue)
{
	XString* const	theXString = m_xstringAllocator.createString(theValue);

	theXString->setFactory(this);

	return XObjectPtr(theXString);
}

const XObjectPtr
XObjectFactoryDefault::createString(const XalanDOMChar*		theValue)
{
	XString* const	theXString = m_xstringAllocator.createString(theValue);

	theXString->setFactory(this);

	return XObjectPtr(theXString);
}

const XObjectPtr
XObjectFactoryDefault::createString(
			const XalanDOMChar*		theValue,
			unsigned int			theLength)
{
	XString* const	theXString = m_xstringAllocator.createString(theValue, theLength);

	theXString->setFactory(this);

	return XObjectPtr(theXString);
}

const XObjectPtr
XObjectFactoryDefault::createString(const XToken&	theValue)
{
	XObject*	theXObject = m_xtokenStringAdapterAllocator.create(theValue);

	theXObject->setFactory(this);

	return XObjectPtr(theXObject);
}

const XObjectPtr
XObjectFactoryDefault::createStringReference(const XalanDOMString&	theValue)
{
	XStringReference* const	theXStringReference = m_xstringReferenceAllocator.createString(theValue);

	theXStringReference->setFactory(this);

	return XObjectPtr(theXStringReference);
}

const XObjectPtr
XObjectFactoryDefault::createStringAdapter(const XObjectPtr&	theValue)
{
	XStringAdapter* const	theXStringAdapter = m_xstringAdapterAllocator.createString(theValue);

	theXStringAdapter->setFactory(this);

	return XObjectPtr(theXStringAdapter);
}

const XObjectPtr
XObjectFactoryDefault::createString(GetAndReleaseCachedString&	theValue)
{
	XStringCached* const	theXStringCached = m_xstringCachedAllocator.createString(theValue);

	theXStringCached->setFactory(this);

	return XObjectPtr(theXStringCached);
}

const XObjectPtr
XObjectFactoryDefault::createResultTreeFrag(BorrowReturnResultTreeFrag&		theValue)
{
	if (m_xresultTreeFragCache.size() > 0)
	{
		XResultTreeFrag* const	theResultTreeFrag = m_xresultTreeFragCache.back();

		m_xresultTreeFragCache.pop_back();

		theResultTreeFrag->set(theValue);

		return XObjectPtr(theResultTreeFrag);
	}
	else
	{
		m_xresultTreeFragCache.reserve(eXResultTreeFragCacheMax);

		XResultTreeFrag* const	theResultTreeFrag =  m_xresultTreeFragAllocator.create(theValue);

		theResultTreeFrag->setFactory(this);

		return XObjectPtr(theResultTreeFrag);
	}
}

void
XObjectFactoryDefault::reset()
{
	m_xstringAdapterAllocator.reset();

	m_xstringAllocator.reset();

	m_xstringReferenceAllocator.reset();

	m_xnumberAllocator.reset();

	m_xnodesetAllocator.reset();

	m_xresultTreeFragAllocator.reset();

#if !defined(XALAN_NO_NAMESPACES)
	using std::for_each;
#endif

	for_each(m_xobjects.begin(),
			 m_xobjects.end(),
			 DeleteXObjectFunctor(*this, true));

	m_xobjects.clear();

	m_xnumberCache.clear();

	m_xnodesetCache.clear();
}
<commit_msg>Fixed bug were result tree cache wasn't cleared in reset().<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
// Class header file...
#include "XObjectFactoryDefault.hpp"

#include <algorithm>
#include <memory>

#include "XBoolean.hpp"
#include "XNodeSet.hpp"
#include "XNull.hpp"
#include "XNumber.hpp"
#include "XResultTreeFrag.hpp"
#include "XSpan.hpp"
#include "XString.hpp"
#include "XStringAdapter.hpp"
#include "XStringCached.hpp"
#include "XStringReference.hpp"
#include "XUnknown.hpp"

XObjectFactoryDefault::XObjectFactoryDefault(
			unsigned int	theXStringBlockSize,
			unsigned int	theXNumberBlockSize,
			unsigned int	theXNodeSetBlockSize,
			unsigned int	theXResultTreeFragBlockSize) :
	XObjectFactory(),
	m_xstringAdapterAllocator(theXStringBlockSize),
	m_xstringAllocator(theXStringBlockSize),
	m_xstringCachedAllocator(theXStringBlockSize),
	m_xstringReferenceAllocator(theXStringBlockSize),
	m_xnumberAllocator(theXNumberBlockSize),
	m_xnodesetAllocator(theXNodeSetBlockSize),
	m_xresultTreeFragAllocator(theXResultTreeFragBlockSize),
	m_xtokenNumberAdapterAllocator(theXNumberBlockSize),
	m_xtokenStringAdapterAllocator(theXStringBlockSize),
	m_xobjects(),
	m_xnumberCache(),
	m_xnodesetCache(),
	m_xresultTreeFragCache(),
	m_XNull(new XNull),
	m_xbooleanFalse(new XBoolean(false)),
	m_xbooleanTrue(new XBoolean(true))
{
}

XObjectFactoryDefault::~XObjectFactoryDefault()
{
	reset();
}

bool
XObjectFactoryDefault::doReturnObject(
			XObject*	theXObject,
			bool		fInReset)
{
	assert(theXObject != 0);

	bool bStatus = false;

	const XObject::eObjectType	theType = getRealType(*theXObject);

	switch(theType)
	{
	case XObject::eTypeBoolean:
	case XObject::eTypeNull:
		{
			bStatus = true;
		}

	case XObject::eTypeStringAdapter:
		{
			XStringAdapter* const		theXStringAdapter =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XStringAdapter*)theXObject;
#else
				static_cast<XStringAdapter*>(theXObject);
#endif

			bStatus = m_xstringAdapterAllocator.destroy(theXStringAdapter);
		}
		break;

	case XObject::eTypeXTokenNumberAdapter:
		{
			XTokenNumberAdapter* const	theAdapter =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XTokenNumberAdapter*)theXObject;
#else
				static_cast<XTokenNumberAdapter*>(theXObject);
#endif

			bStatus = m_xtokenNumberAdapterAllocator.destroy(theAdapter);
		}
		break;

	case XObject::eTypeXTokenStringAdapter:
		{
			XTokenStringAdapter* const	theAdapter =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XTokenStringAdapter*)theXObject;
#else
				static_cast<XTokenStringAdapter*>(theXObject);
#endif

			bStatus = m_xtokenStringAdapterAllocator.destroy(theAdapter);
		}
		break;

	case XObject::eTypeString:
		{
			XString* const	theXString =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XString*)theXObject;
#else
				static_cast<XString*>(theXObject);
#endif

			bStatus = m_xstringAllocator.destroy(theXString);
		}
		break;

	case XObject::eTypeStringCached:
		{
			XStringCached* const	theXStringCached =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XStringCached*)theXObject;
#else
				static_cast<XStringCached*>(theXObject);
#endif

			bStatus = m_xstringCachedAllocator.destroy(theXStringCached);
		}
		break;

	case XObject::eTypeStringReference:
		{
			XStringReference* const		theXStringReference =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XStringReference*)theXObject;
#else
				static_cast<XStringReference*>(theXObject);
#endif

			bStatus = m_xstringReferenceAllocator.destroy(theXStringReference);
		}
		break;

	case  XObject::eTypeNumber:
		{
			XNumber* const	theXNumber =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XNumber*)theXObject;
#else
				static_cast<XNumber*>(theXObject);
#endif

			if (m_xnumberCache.size() < eXNumberCacheMax)
			{
				m_xnumberCache.push_back(theXNumber);

				bStatus = true;
			}
			else
			{
				bStatus = m_xnumberAllocator.destroy(theXNumber);
			}
		}
		break;

	case XObject::eTypeNodeSet:
		{
			XNodeSet* const		theXNodeSet =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XNodeSet*)theXObject;
#else
				static_cast<XNodeSet*>(theXObject);
#endif

			if (m_xnodesetCache.size() < eXNodeSetCacheMax)
			{
				theXNodeSet->release();

				m_xnodesetCache.push_back(theXNodeSet);

				bStatus = true;
			}
			else
			{
				bStatus = m_xnodesetAllocator.destroy(theXNodeSet);
			}
		}
		break;

	case XObject::eTypeResultTreeFrag:
		{
			XResultTreeFrag* const	theXResultTreeFrag =
#if defined(XALAN_OLD_STYLE_CASTS)
				(XResultTreeFrag*)theXObject;
#else
				static_cast<XResultTreeFrag*>(theXObject);
#endif

			if (m_xresultTreeFragCache.size() < eXResultTreeFragCacheMax)
			{
				m_xresultTreeFragCache.push_back(theXResultTreeFrag);

				bStatus = true;
			}
			else
			{
				bStatus = m_xresultTreeFragAllocator.destroy(theXResultTreeFrag);
			}
		}
		break;

	default:
		{
#if !defined(XALAN_NO_NAMESPACES)
			using std::find;
#endif

			const XObjectCollectionType::iterator	i =
					find(m_xobjects.begin(), m_xobjects.end(), theXObject);

			if (i != m_xobjects.end())
			{
				if (fInReset == false)
				{
					m_xobjects.erase(i);
				}

				deleteObject(theXObject);

				bStatus = true;
			}
		}
		break;
	}

	return bStatus;
}

const XObjectPtr
XObjectFactoryDefault::createBoolean(
			bool	theValue)
{
	if (theValue == true)
	{
		return XObjectPtr(m_xbooleanTrue.get());
	}
	else
	{
		return XObjectPtr(m_xbooleanFalse.get());
	}
}

const XObjectPtr
XObjectFactoryDefault::createNull()
{
	return XObjectPtr(m_XNull.get());
}

const XObjectPtr
XObjectFactoryDefault::createUnknown(const XalanDOMString&	theValue)
{
	XUnknown* const	theXUnknown = new XUnknown(theValue);

	m_xobjects.push_back(theXUnknown);

	theXUnknown->setFactory(this);

	return XObjectPtr(theXUnknown);
}

const XObjectPtr
XObjectFactoryDefault::createSpan(BorrowReturnMutableNodeRefList&	theValue)
{
	XSpan* const	theXObject = new XSpan(theValue);

	m_xobjects.push_back(theXObject);

	theXObject->setFactory(this);

	return XObjectPtr(theXObject);
}

const XObjectPtr
XObjectFactoryDefault::createNumber(double	theValue)
{
	if (m_xnumberCache.size() > 0)
	{
		XNumber* const	theXNumber = m_xnumberCache.back();

		m_xnumberCache.pop_back();

		theXNumber->set(theValue);

		return XObjectPtr(theXNumber);
	}
	else
	{
		m_xnumberCache.reserve(eXNumberCacheMax);

		XObject* const	theXObject = m_xnumberAllocator.createNumber(theValue);

		theXObject->setFactory(this);

		return XObjectPtr(theXObject);
	}
}

const XObjectPtr
XObjectFactoryDefault::createNumber(const XToken&	theValue)
{
	XObject*	theXObject = m_xtokenNumberAdapterAllocator.create(theValue);

	theXObject->setFactory(this);

	return XObjectPtr(theXObject);
}

const XObjectPtr
XObjectFactoryDefault::createNodeSet(BorrowReturnMutableNodeRefList&	theValue)
{
	if (m_xnodesetCache.size() > 0)
	{
		XNodeSet* const		theXObject = m_xnodesetCache.back();

		m_xnodesetCache.pop_back();

		theXObject->set(theValue);

		return XObjectPtr(theXObject);
	}
	else
	{
		m_xnodesetCache.reserve(eXNodeSetCacheMax);

		XNodeSet* const		theXObject = m_xnodesetAllocator.createNodeSet(theValue);

		theXObject->setFactory(this);

		return XObjectPtr(theXObject);
	}
}

const XObjectPtr
XObjectFactoryDefault::createString(const XalanDOMString&	theValue)
{
	XString* const	theXString = m_xstringAllocator.createString(theValue);

	theXString->setFactory(this);

	return XObjectPtr(theXString);
}

const XObjectPtr
XObjectFactoryDefault::createString(const XalanDOMChar*		theValue)
{
	XString* const	theXString = m_xstringAllocator.createString(theValue);

	theXString->setFactory(this);

	return XObjectPtr(theXString);
}

const XObjectPtr
XObjectFactoryDefault::createString(
			const XalanDOMChar*		theValue,
			unsigned int			theLength)
{
	XString* const	theXString = m_xstringAllocator.createString(theValue, theLength);

	theXString->setFactory(this);

	return XObjectPtr(theXString);
}

const XObjectPtr
XObjectFactoryDefault::createString(const XToken&	theValue)
{
	XObject*	theXObject = m_xtokenStringAdapterAllocator.create(theValue);

	theXObject->setFactory(this);

	return XObjectPtr(theXObject);
}

const XObjectPtr
XObjectFactoryDefault::createStringReference(const XalanDOMString&	theValue)
{
	XStringReference* const	theXStringReference = m_xstringReferenceAllocator.createString(theValue);

	theXStringReference->setFactory(this);

	return XObjectPtr(theXStringReference);
}

const XObjectPtr
XObjectFactoryDefault::createStringAdapter(const XObjectPtr&	theValue)
{
	XStringAdapter* const	theXStringAdapter = m_xstringAdapterAllocator.createString(theValue);

	theXStringAdapter->setFactory(this);

	return XObjectPtr(theXStringAdapter);
}

const XObjectPtr
XObjectFactoryDefault::createString(GetAndReleaseCachedString&	theValue)
{
	XStringCached* const	theXStringCached = m_xstringCachedAllocator.createString(theValue);

	theXStringCached->setFactory(this);

	return XObjectPtr(theXStringCached);
}

const XObjectPtr
XObjectFactoryDefault::createResultTreeFrag(BorrowReturnResultTreeFrag&		theValue)
{
	if (m_xresultTreeFragCache.size() > 0)
	{
		XResultTreeFrag* const	theResultTreeFrag = m_xresultTreeFragCache.back();

		m_xresultTreeFragCache.pop_back();

		theResultTreeFrag->set(theValue);

		return XObjectPtr(theResultTreeFrag);
	}
	else
	{
		m_xresultTreeFragCache.reserve(eXResultTreeFragCacheMax);

		XResultTreeFrag* const	theResultTreeFrag =  m_xresultTreeFragAllocator.create(theValue);

		theResultTreeFrag->setFactory(this);

		return XObjectPtr(theResultTreeFrag);
	}
}

void
XObjectFactoryDefault::reset()
{
	m_xstringAdapterAllocator.reset();

	m_xstringAllocator.reset();

	m_xstringReferenceAllocator.reset();

	m_xnumberAllocator.reset();

	m_xnodesetAllocator.reset();

	m_xresultTreeFragAllocator.reset();

#if !defined(XALAN_NO_NAMESPACES)
	using std::for_each;
#endif

	for_each(m_xobjects.begin(),
			 m_xobjects.end(),
			 DeleteXObjectFunctor(*this, true));

	m_xobjects.clear();

	m_xnumberCache.clear();

	m_xnodesetCache.clear();

	m_xresultTreeFragCache.clear();
}
<|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 "chrome/app/chrome_dll_resource.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_layout_test.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/escape.h"
#include "net/test/test_server.h"

struct IsSearchProviderTestData;

class SearchProviderTest : public UITest {
 protected:
  SearchProviderTest();

  IsSearchProviderTestData StartIsSearchProviderInstalledTest(
      BrowserProxy* browser_proxy,
      const char* host,
      const char* expected_result);

  void FinishIsSearchProviderInstalledTest(
      const IsSearchProviderTestData& data);

  net::TestServer test_server_;

 private:
  DISALLOW_COPY_AND_ASSIGN(SearchProviderTest);
};

SearchProviderTest::SearchProviderTest()
    : test_server_(net::TestServer::TYPE_HTTP,
                   FilePath(FILE_PATH_LITERAL("chrome/test/data"))) {
  // Enable the search provider additions.
  launch_arguments_.AppendSwitch(switches::kEnableSearchProviderApiV2);

  // Map all hosts to our local server.
  std::string host_rule("MAP * " + test_server_.host_port_pair().ToString());
  launch_arguments_.AppendSwitchASCII(switches::kHostRules, host_rule);
}

struct IsSearchProviderTestData {
  IsSearchProviderTestData() {
  }

  IsSearchProviderTestData(TabProxy* t,
                           std::string h,
                           GURL url)
      : tab(t),
        host(h),
        test_url(url) {
  }

  scoped_refptr<TabProxy> tab;
  std::string host;
  GURL test_url;
};

IsSearchProviderTestData SearchProviderTest::StartIsSearchProviderInstalledTest(
    BrowserProxy* browser_proxy,
    const char* host,
    const char* expected_result) {
  // Set-up a new tab for the navigation.
  int num_tabs = 0;
  if (!browser_proxy->GetTabCount(&num_tabs)) {
    ADD_FAILURE() << "BrowserProxy::GetTabCount failed.";
    return IsSearchProviderTestData();
  }

  GURL blank(chrome::kAboutBlankURL);
  if (!browser_proxy->AppendTab(blank)) {
    ADD_FAILURE() << "BrowserProxy::AppendTab failed.";
    return IsSearchProviderTestData();
  }

  scoped_refptr<TabProxy> tab(browser_proxy->GetTab(num_tabs));
  if (!tab.get()) {
    ADD_FAILURE() << "BrowserProxy::GetTab for the new tab failed.";
    return IsSearchProviderTestData();
  }

  // Go to the test page.
  GURL local_url =
      test_server_.GetURL("files/is_search_provider_installed.html");
  GURL test_url(std::string("http://") + host + local_url.path() +
                "#" + expected_result);
  EXPECT_TRUE(tab->NavigateToURLAsync(test_url));

  // Bundle up information needed to verify the result.
  return IsSearchProviderTestData(tab, host, test_url);
}

void SearchProviderTest::FinishIsSearchProviderInstalledTest(
    const IsSearchProviderTestData& data) {
  ASSERT_TRUE(data.tab.get());

  std::string cookie_name = data.host + "testResult";
  std::string escaped_value =
      WaitUntilCookieNonEmpty(data.tab, data.test_url,
                              cookie_name.c_str(), action_max_timeout_ms());

  // Unescapes and normalizes the actual result.
  std::string value = UnescapeURLComponent(
      escaped_value,
      UnescapeRule::NORMAL | UnescapeRule::SPACES |
      UnescapeRule::URL_SPECIAL_CHARS | UnescapeRule::CONTROL_CHARS);
  value += "\n";
  ReplaceSubstringsAfterOffset(&value, 0, "\r", "");
  EXPECT_STREQ("1\n", value.c_str());
}

TEST_F(SearchProviderTest, TestIsSearchProviderInstalled) {
  ASSERT_TRUE(test_server_.Start());

  // Use the default search provider, other installed search provider, and
  // one not installed as well. (Note that yahoo isn't tested because the
  // its host name varies a lot for different locales unlike Google and Bing,
  // which would make the test fail depending on the machine's locale.)
  const char* test_hosts[] = { "www.google.com",
                               "www.bing.com",
                               "localhost" };
  const char* expected_results[] = { "2",
                                     "1",
                                     "0" };
  COMPILE_ASSERT(arraysize(test_hosts) == arraysize(expected_results),
                 there_should_be_a_result_for_each_host);
  IsSearchProviderTestData test_data[2 * arraysize(test_hosts)];

  // Start results for the normal mode.
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());
  for (size_t i = 0; i < arraysize(test_hosts); ++i) {
    test_data[i] = StartIsSearchProviderInstalledTest(
        browser, test_hosts[i], expected_results[i]);
    FinishIsSearchProviderInstalledTest(test_data[i]);
  }

  // Start tests for incognito mode (and verify the result is 0).
  ASSERT_TRUE(browser->RunCommand(IDC_NEW_INCOGNITO_WINDOW));
  scoped_refptr<BrowserProxy> incognito(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(incognito.get());
  for (size_t i = 0; i < arraysize(test_hosts); ++i) {
    test_data[i + arraysize(test_hosts)] = StartIsSearchProviderInstalledTest(
        incognito, test_hosts[i], "0");
    FinishIsSearchProviderInstalledTest(test_data[i + arraysize(test_hosts)]);
  }

  // The following should be re-enabled. At the moment, there are problems with
  // doing all of these queries in parallel -- see http://crbug.com/60043.
#if 0
  // Remove the calls to FinishIsSearchProviderInstalledTest above when
  // re-enabling this code.

  // Do the verification.
  for (size_t i = 0; i < arraysize(test_data); ++i) {
    FinishIsSearchProviderInstalledTest(test_data[i]);
  }
#endif
}
<commit_msg>This change moves the test_server_.Start from the test body to the test constructor. This needs to be done so the browser launch arguments can include the correct port in the mapping rules.<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 "chrome/app/chrome_dll_resource.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_layout_test.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/escape.h"
#include "net/test/test_server.h"

struct IsSearchProviderTestData;

class SearchProviderTest : public UITest {
 protected:
  SearchProviderTest();

  IsSearchProviderTestData StartIsSearchProviderInstalledTest(
      BrowserProxy* browser_proxy,
      const char* host,
      const char* expected_result);

  void FinishIsSearchProviderInstalledTest(
      const IsSearchProviderTestData& data);

  net::TestServer test_server_;
  bool test_server_started_;

 private:
  DISALLOW_COPY_AND_ASSIGN(SearchProviderTest);
};

SearchProviderTest::SearchProviderTest()
    : test_server_(net::TestServer::TYPE_HTTP,
                   FilePath(FILE_PATH_LITERAL("chrome/test/data"))),
      test_server_started_(false) {
  // The test_server is started in the constructor (rather than the test body)
  // so the mapping rules below can include the ephemeral port number.
  test_server_started_ = test_server_.Start();
  if (!test_server_started_)
    return;

  // Enable the search provider additions.
  launch_arguments_.AppendSwitch(switches::kEnableSearchProviderApiV2);

  // Map all hosts to our local server.
  std::string host_rule("MAP * " + test_server_.host_port_pair().ToString());
  launch_arguments_.AppendSwitchASCII(switches::kHostRules, host_rule);
}

struct IsSearchProviderTestData {
  IsSearchProviderTestData() {
  }

  IsSearchProviderTestData(TabProxy* t,
                           std::string h,
                           GURL url)
      : tab(t),
        host(h),
        test_url(url) {
  }

  scoped_refptr<TabProxy> tab;
  std::string host;
  GURL test_url;
};

IsSearchProviderTestData SearchProviderTest::StartIsSearchProviderInstalledTest(
    BrowserProxy* browser_proxy,
    const char* host,
    const char* expected_result) {
  // Set-up a new tab for the navigation.
  int num_tabs = 0;
  if (!browser_proxy->GetTabCount(&num_tabs)) {
    ADD_FAILURE() << "BrowserProxy::GetTabCount failed.";
    return IsSearchProviderTestData();
  }

  GURL blank(chrome::kAboutBlankURL);
  if (!browser_proxy->AppendTab(blank)) {
    ADD_FAILURE() << "BrowserProxy::AppendTab failed.";
    return IsSearchProviderTestData();
  }

  scoped_refptr<TabProxy> tab(browser_proxy->GetTab(num_tabs));
  if (!tab.get()) {
    ADD_FAILURE() << "BrowserProxy::GetTab for the new tab failed.";
    return IsSearchProviderTestData();
  }

  // Go to the test page.
  GURL local_url =
      test_server_.GetURL("files/is_search_provider_installed.html");
  GURL test_url(std::string("http://") + host + local_url.path() +
                "#" + expected_result);
  EXPECT_TRUE(tab->NavigateToURLAsync(test_url));

  // Bundle up information needed to verify the result.
  return IsSearchProviderTestData(tab, host, test_url);
}

void SearchProviderTest::FinishIsSearchProviderInstalledTest(
    const IsSearchProviderTestData& data) {
  ASSERT_TRUE(data.tab.get());

  std::string cookie_name = data.host + "testResult";
  std::string escaped_value =
      WaitUntilCookieNonEmpty(data.tab, data.test_url,
                              cookie_name.c_str(), action_max_timeout_ms());

  // Unescapes and normalizes the actual result.
  std::string value = UnescapeURLComponent(
      escaped_value,
      UnescapeRule::NORMAL | UnescapeRule::SPACES |
      UnescapeRule::URL_SPECIAL_CHARS | UnescapeRule::CONTROL_CHARS);
  value += "\n";
  ReplaceSubstringsAfterOffset(&value, 0, "\r", "");
  EXPECT_STREQ("1\n", value.c_str());
}

TEST_F(SearchProviderTest, TestIsSearchProviderInstalled) {
  ASSERT_TRUE(test_server_started_);

  // Use the default search provider, other installed search provider, and
  // one not installed as well. (Note that yahoo isn't tested because the
  // its host name varies a lot for different locales unlike Google and Bing,
  // which would make the test fail depending on the machine's locale.)
  const char* test_hosts[] = { "www.google.com",
                               "www.bing.com",
                               "localhost" };
  const char* expected_results[] = { "2",
                                     "1",
                                     "0" };
  COMPILE_ASSERT(arraysize(test_hosts) == arraysize(expected_results),
                 there_should_be_a_result_for_each_host);
  IsSearchProviderTestData test_data[2 * arraysize(test_hosts)];

  // Start results for the normal mode.
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());
  for (size_t i = 0; i < arraysize(test_hosts); ++i) {
    test_data[i] = StartIsSearchProviderInstalledTest(
        browser, test_hosts[i], expected_results[i]);
    FinishIsSearchProviderInstalledTest(test_data[i]);
  }

  // Start tests for incognito mode (and verify the result is 0).
  ASSERT_TRUE(browser->RunCommand(IDC_NEW_INCOGNITO_WINDOW));
  scoped_refptr<BrowserProxy> incognito(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(incognito.get());
  for (size_t i = 0; i < arraysize(test_hosts); ++i) {
    test_data[i + arraysize(test_hosts)] = StartIsSearchProviderInstalledTest(
        incognito, test_hosts[i], "0");
    FinishIsSearchProviderInstalledTest(test_data[i + arraysize(test_hosts)]);
  }

  // The following should be re-enabled. At the moment, there are problems with
  // doing all of these queries in parallel -- see http://crbug.com/60043.
#if 0
  // Remove the calls to FinishIsSearchProviderInstalledTest above when
  // re-enabling this code.

  // Do the verification.
  for (size_t i = 0; i < arraysize(test_data); ++i) {
    FinishIsSearchProviderInstalledTest(test_data[i]);
  }
#endif
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 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 "chrome/renderer/media/video_renderer_impl.h"
#include "media/base/yuv_convert.h"

VideoRendererImpl::VideoRendererImpl(WebMediaPlayerDelegateImpl* delegate)
    : delegate_(delegate),
      last_converted_frame_(NULL) {
  // TODO(hclam): decide whether to do the following line in this thread or
  // in the render thread.
  delegate_->SetVideoRenderer(this);
}

bool VideoRendererImpl::OnInitialize(size_t width, size_t height) {
  video_size_.SetSize(width, height);
  bitmap_.setConfig(SkBitmap::kARGB_8888_Config, width, height);
  if (bitmap_.allocPixels(NULL, NULL)) {
    bitmap_.eraseRGB(0x00, 0x00, 0x00);
    return true;
  }
  NOTREACHED();
  return false;
}

void VideoRendererImpl::OnPaintNeeded() {
  delegate_->PostRepaintTask();
}

// This method is always called on the renderer's thread.
void VideoRendererImpl::Paint(skia::PlatformCanvas* canvas,
                              const gfx::Rect& dest_rect) {
  scoped_refptr<media::VideoFrame> video_frame;
  GetCurrentFrame(&video_frame);
  if (video_frame.get()) {
    CopyToCurrentFrame(video_frame);
    video_frame = NULL;
  }
  SkMatrix matrix;
  matrix.setTranslate(static_cast<SkScalar>(dest_rect.x()),
                      static_cast<SkScalar>(dest_rect.y()));
  if (dest_rect.width()  != video_size_.width() ||
      dest_rect.height() != video_size_.height()) {
    matrix.preScale(
        static_cast<SkScalar>(dest_rect.width()  / video_size_.width()),
        static_cast<SkScalar>(dest_rect.height() / video_size_.height()));
  }
  canvas->drawBitmapMatrix(bitmap_, matrix, NULL);
}

void VideoRendererImpl::CopyToCurrentFrame(media::VideoFrame* video_frame) {
  base::TimeDelta timestamp = video_frame->GetTimestamp();
  if (video_frame != last_converted_frame_ ||
      timestamp != last_converted_timestamp_) {
    last_converted_frame_ = video_frame;
    last_converted_timestamp_ = timestamp;
    media::VideoSurface frame_in;
    if (video_frame->Lock(&frame_in)) {
      // TODO(hclam): Support more video formats than just YV12.
      DCHECK(frame_in.format == media::VideoSurface::YV12);
      DCHECK(frame_in.strides[media::VideoSurface::kUPlane] ==
             frame_in.strides[media::VideoSurface::kVPlane]);
      DCHECK(frame_in.planes == media::VideoSurface::kNumYUVPlanes);
      bitmap_.lockPixels();
      media::ConvertYV12ToRGB32(frame_in.data[media::VideoSurface::kYPlane],
                                frame_in.data[media::VideoSurface::kUPlane],
                                frame_in.data[media::VideoSurface::kVPlane],
                                static_cast<uint8*>(bitmap_.getPixels()),
                                frame_in.width,
                                frame_in.height,
                                frame_in.strides[media::VideoSurface::kYPlane],
                                frame_in.strides[media::VideoSurface::kUPlane],
                                bitmap_.rowBytes());
      bitmap_.unlockPixels();
      video_frame->Unlock();
    } else {
      NOTREACHED();
    }
  }
}
<commit_msg>TBR=ralphl, scherkus VideoRendererImpl did an incorrect scaling matrix, resulting in no video image drawn.<commit_after>// Copyright (c) 2009 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 "chrome/renderer/media/video_renderer_impl.h"
#include "media/base/yuv_convert.h"

VideoRendererImpl::VideoRendererImpl(WebMediaPlayerDelegateImpl* delegate)
    : delegate_(delegate),
      last_converted_frame_(NULL) {
  // TODO(hclam): decide whether to do the following line in this thread or
  // in the render thread.
  delegate_->SetVideoRenderer(this);
}

bool VideoRendererImpl::OnInitialize(size_t width, size_t height) {
  video_size_.SetSize(width, height);
  bitmap_.setConfig(SkBitmap::kARGB_8888_Config, width, height);
  if (bitmap_.allocPixels(NULL, NULL)) {
    bitmap_.eraseRGB(0x00, 0x00, 0x00);
    return true;
  }
  NOTREACHED();
  return false;
}

void VideoRendererImpl::OnPaintNeeded() {
  delegate_->PostRepaintTask();
}

// This method is always called on the renderer's thread.
void VideoRendererImpl::Paint(skia::PlatformCanvas* canvas,
                              const gfx::Rect& dest_rect) {
  scoped_refptr<media::VideoFrame> video_frame;
  GetCurrentFrame(&video_frame);
  if (video_frame.get()) {
    CopyToCurrentFrame(video_frame);
    video_frame = NULL;
  }
  SkMatrix matrix;
  matrix.setTranslate(static_cast<SkScalar>(dest_rect.x()),
                      static_cast<SkScalar>(dest_rect.y()));
  if (dest_rect.width()  != video_size_.width() ||
      dest_rect.height() != video_size_.height()) {
    matrix.preScale(SkIntToScalar(dest_rect.width()) /
                    SkIntToScalar(video_size_.width()),
                    SkIntToScalar(dest_rect.height()) /
                    SkIntToScalar(video_size_.height()));
  }
  canvas->drawBitmapMatrix(bitmap_, matrix, NULL);
}

void VideoRendererImpl::CopyToCurrentFrame(media::VideoFrame* video_frame) {
  base::TimeDelta timestamp = video_frame->GetTimestamp();
  if (video_frame != last_converted_frame_ ||
      timestamp != last_converted_timestamp_) {
    last_converted_frame_ = video_frame;
    last_converted_timestamp_ = timestamp;
    media::VideoSurface frame_in;
    if (video_frame->Lock(&frame_in)) {
      // TODO(hclam): Support more video formats than just YV12.
      DCHECK(frame_in.format == media::VideoSurface::YV12);
      DCHECK(frame_in.strides[media::VideoSurface::kUPlane] ==
             frame_in.strides[media::VideoSurface::kVPlane]);
      DCHECK(frame_in.planes == media::VideoSurface::kNumYUVPlanes);
      bitmap_.lockPixels();
      media::ConvertYV12ToRGB32(frame_in.data[media::VideoSurface::kYPlane],
                                frame_in.data[media::VideoSurface::kUPlane],
                                frame_in.data[media::VideoSurface::kVPlane],
                                static_cast<uint8*>(bitmap_.getPixels()),
                                frame_in.width,
                                frame_in.height,
                                frame_in.strides[media::VideoSurface::kYPlane],
                                frame_in.strides[media::VideoSurface::kUPlane],
                                bitmap_.rowBytes());
      bitmap_.unlockPixels();
      video_frame->Unlock();
    } else {
      NOTREACHED();
    }
  }
}
<|endoftext|>


<commit_before>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999 Stefan Seefeld <seefelds@magellan.umontreal.ca>
 * Copyright (C) 1999 Graydon Hoare <graydon@pobox.com>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */
#include "Berlin/Memory.hh"
#include "Drawing/openGL/Pointer.hh"
extern "C"
{
#include "ggi/ggi.h"
}
#include <iostream>
#include <algorithm>

static unsigned char pointerImg[256] =

{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
  1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,
  1,2,2,2,1,0,0,0,0,0,0,0,0,0,0,0,
  1,2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,
  1,2,2,2,2,2,1,0,0,0,0,0,0,0,0,0,
  1,2,2,2,2,2,2,1,0,0,0,0,0,0,0,0,
  1,2,2,2,2,2,2,2,1,0,0,0,0,0,0,0,
  1,2,2,2,2,2,1,1,1,1,0,0,0,0,0,0,
  1,2,2,1,2,2,1,0,0,0,0,0,0,0,0,0,
  1,1,0,1,2,2,2,1,0,0,0,0,0,0,0,0,
  1,0,0,0,1,2,2,1,0,0,0,0,0,0,0,0,
  0,0,0,0,1,2,2,2,1,0,0,0,0,0,0,0,
  0,0,0,0,0,1,2,2,1,0,0,0,0,0,0,0,
  0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0 };

Pointer::Pointer(ggi_visual_t visual)
{
  origin[0] = origin[1] = 0;
  position[0] = position[1] = 8;
  size[0] = size[1] = 16;

  if (!(dbuf = ggiDBGetBuffer (visual, 0)) )
    cerr << "Error getting display buffer" << endl;
  else if (dbuf->layout != blPixelLinearBuffer)
    cerr << "Error: nonlinear display buffer" << endl;
  else if (! (dbuf->type & GGI_DB_SIMPLE_PLB))
    cerr << "Error: non-standard display buffer" << endl;
  depth = dbuf->buffer.plb.pixelformat->size >> 3;
  stride = dbuf->buffer.plb.stride;

  ggi_mode m;
  ggiGetMode(visual, &m);
  maxCoord = m.virt.x * m.virt.y;

  /*
   * create the pointer image
   */
  image = new unsigned char[size[0]*size[1]*depth];
  for (unsigned short y = 0; y != size[1]; y++)
    for (unsigned short x = 0; x != size[0]; x++)
	for (unsigned short d = 0; d != depth; d++)
	    image[y*depth*size[0] + depth*x + d] = pointerImg[y*size[0] +x] * 127;

  /*
   * create the pointer mask
   */
  mask = new unsigned char[size[0]*size[1]*depth];
  for (unsigned short y = 0; y != size[1]; y++)
      for (unsigned short x = 0; x != size[0]; x++)
	  for (unsigned short d = 0; d != depth; d++)
	      mask[y*depth*size[0] + depth*x + d] = pointerImg[y*size[0] +x] > 0 ? ~0 : 0;

  cache = new unsigned char[size[0]*size[1]*depth];
  backup();
}

Pointer::~Pointer()
{
  delete [] image;
  delete [] mask;
  delete [] cache;
}

void Pointer::move(PixelCoord x, PixelCoord y)
{
  restore();
  position[0] = max(x, origin[0]);
  position[1] = max(y, origin[1]);
  backup();
  draw();
};

#define PIXPOS  (((position[1] + y) - origin[1])*(stride/depth) + (position[0]-origin[0]) + size[0])

void Pointer::backup()
{
  unsigned char *from = static_cast<unsigned char *>(dbuf->read) + (position[1]-origin[1])*stride + (position[0]-origin[0])*depth;
  unsigned char *to = cache;
  for (PixelCoord y = 0; (y != size[1]) && (PIXPOS < maxCoord); y++, from += stride, to += depth*size[0])
    Memory::copy(from, to, depth*size[0]);
}

void Pointer::restore()
{
  unsigned char *from = cache;
  unsigned char *to = static_cast<unsigned char *>(dbuf->write) + (position[1]-origin[1])*stride + (position[0]-origin[0])*depth;
  for (PixelCoord y = 0; (y != size[1]) && (PIXPOS < maxCoord); y++, from += depth*size[0], to += stride)
    Memory::copy(from, to, depth*size[0]);
}

void Pointer::draw()
{
  unsigned char *from = image;
  unsigned char *bits = mask;
  unsigned char *to = static_cast<unsigned char *>(dbuf->write) + (position[1]-origin[1])*stride + (position[0]-origin[0])*depth;

  for (PixelCoord y = 0; (y != size[1]) && (PIXPOS < maxCoord); y++, to += stride - size[0]*depth)
    for (PixelCoord x = 0; x != size[0]*depth; x++, from++, bits++, to++)
	*to = (*from & *bits) | (*to & ~*bits);

	    //	    *to = *from & *bits;
}
<commit_msg>*** empty log message ***<commit_after>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999 Stefan Seefeld <seefelds@magellan.umontreal.ca>
 * Copyright (C) 1999 Graydon Hoare <graydon@pobox.com>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */
#include "Prague/Sys/Memory.hh"
#include "Drawing/openGL/Pointer.hh"
extern "C"
{
#include "ggi/ggi.h"
}
#include <iostream>
#include <algorithm>

using namespace Prague;

static unsigned char pointerImg[256] =

{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
  1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,
  1,2,2,2,1,0,0,0,0,0,0,0,0,0,0,0,
  1,2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,
  1,2,2,2,2,2,1,0,0,0,0,0,0,0,0,0,
  1,2,2,2,2,2,2,1,0,0,0,0,0,0,0,0,
  1,2,2,2,2,2,2,2,1,0,0,0,0,0,0,0,
  1,2,2,2,2,2,1,1,1,1,0,0,0,0,0,0,
  1,2,2,1,2,2,1,0,0,0,0,0,0,0,0,0,
  1,1,0,1,2,2,2,1,0,0,0,0,0,0,0,0,
  1,0,0,0,1,2,2,1,0,0,0,0,0,0,0,0,
  0,0,0,0,1,2,2,2,1,0,0,0,0,0,0,0,
  0,0,0,0,0,1,2,2,1,0,0,0,0,0,0,0,
  0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0 };

Pointer::Pointer(ggi_visual_t visual)
{
  origin[0] = origin[1] = 0;
  position[0] = position[1] = 8;
  size[0] = size[1] = 16;

  if (!(dbuf = ggiDBGetBuffer (visual, 0)) )
    cerr << "Error getting display buffer" << endl;
  else if (dbuf->layout != blPixelLinearBuffer)
    cerr << "Error: nonlinear display buffer" << endl;
  else if (! (dbuf->type & GGI_DB_SIMPLE_PLB))
    cerr << "Error: non-standard display buffer" << endl;
  depth = dbuf->buffer.plb.pixelformat->size >> 3;
  stride = dbuf->buffer.plb.stride;

  ggi_mode m;
  ggiGetMode(visual, &m);
  maxCoord = m.virt.x * m.virt.y;

  /*
   * create the pointer image
   */
  image = new unsigned char[size[0]*size[1]*depth];
  for (unsigned short y = 0; y != size[1]; y++)
    for (unsigned short x = 0; x != size[0]; x++)
	for (unsigned short d = 0; d != depth; d++)
	    image[y*depth*size[0] + depth*x + d] = pointerImg[y*size[0] +x] * 127;

  /*
   * create the pointer mask
   */
  mask = new unsigned char[size[0]*size[1]*depth];
  for (unsigned short y = 0; y != size[1]; y++)
      for (unsigned short x = 0; x != size[0]; x++)
	  for (unsigned short d = 0; d != depth; d++)
	      mask[y*depth*size[0] + depth*x + d] = pointerImg[y*size[0] +x] > 0 ? ~0 : 0;

  cache = new unsigned char[size[0]*size[1]*depth];
  backup();
}

Pointer::~Pointer()
{
  delete [] image;
  delete [] mask;
  delete [] cache;
}

void Pointer::move(PixelCoord x, PixelCoord y)
{
  restore();
  position[0] = max(x, origin[0]);
  position[1] = max(y, origin[1]);
  backup();
  draw();
};

#define PIXPOS  (((position[1] + y) - origin[1])*(stride/depth) + (position[0]-origin[0]) + size[0])

void Pointer::backup()
{
  unsigned char *from = static_cast<unsigned char *>(dbuf->read) + (position[1]-origin[1])*stride + (position[0]-origin[0])*depth;
  unsigned char *to = cache;
  for (PixelCoord y = 0; (y != size[1]) && (PIXPOS < maxCoord); y++, from += stride, to += depth*size[0])
    Memory::copy(from, to, depth*size[0]);
}

void Pointer::restore()
{
  unsigned char *from = cache;
  unsigned char *to = static_cast<unsigned char *>(dbuf->write) + (position[1]-origin[1])*stride + (position[0]-origin[0])*depth;
  for (PixelCoord y = 0; (y != size[1]) && (PIXPOS < maxCoord); y++, from += depth*size[0], to += stride)
    Memory::copy(from, to, depth*size[0]);
}

void Pointer::draw()
{
  unsigned char *from = image;
  unsigned char *bits = mask;
  unsigned char *to = static_cast<unsigned char *>(dbuf->write) + (position[1]-origin[1])*stride + (position[0]-origin[0])*depth;

  for (PixelCoord y = 0; (y != size[1]) && (PIXPOS < maxCoord); y++, to += stride - size[0]*depth)
    for (PixelCoord x = 0; x != size[0]*depth; x++, from++, bits++, to++)
	*to = (*from & *bits) | (*to & ~*bits);

	    //	    *to = *from & *bits;
}
<|endoftext|>


<commit_before>#ifndef INCLUDE_UNITTESTS_OpenMeshAddFaceTriangleMesh_HH
#define INCLUDE_UNITTESTS_OpenMeshAddFaceTriangleMesh_HH

#include <gtest/gtest.h>
#include <Unittests/unittests_common.hh>
#include <iostream>

class OpenMeshAddFaceTriangleMesh : public OpenMeshBase {

    protected:

        // This function is called before each test is run
        virtual void SetUp() {

            // Do some initial stuff with the member data here...
        }

        // This function is called after all tests are through
        virtual void TearDown() {

            // Do some final stuff with the member data here...
        }

    // Member already defined in OpenMeshBase
    //Mesh mesh_;
};

class OpenMeshAddFacePolyMesh : public OpenMeshBasePoly {

    protected:

        // This function is called before each test is run
        virtual void SetUp() {

            // Do some initial stuff with the member data here...
        }

        // This function is called after all tests are through
        virtual void TearDown() {

            // Do some final stuff with the member data here...
        }

    // Member already defined in OpenMeshBase
    //Mesh mesh_;
};

/*
 * ====================================================================
 * Define tests below
 * ====================================================================
 */

/* Adds two triangles to a tri mesh
 */
TEST_F(OpenMeshAddFaceTriangleMesh, AddTrianglesToTrimesh) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[4];

  vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
  vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
  vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));

  // Add two faces
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[0]);

  mesh_.add_face(face_vhandles);

  face_vhandles.clear();

  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[3]);
  mesh_.add_face(face_vhandles);

  // Test setup:
  //  1 === 2
  //  |   / |
  //  |  /  |
  //  | /   |
  //  0 === 3

  // Check setup
  EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(2u, mesh_.n_faces() )    << "Wrong number of faces";

}

/* Adds a quad to a trimesh (should be triangulated afterwards)
 */
TEST_F(OpenMeshAddFaceTriangleMesh, AddQuadToTrimesh) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[4];

  vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
  vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
  vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));

  // Add two faces
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);

  mesh_.add_face(face_vhandles);

  // Test setup:
  //  1 === 2
  //  |   / |
  //  |  /  |
  //  | /   |
  //  0 === 3

  // Check setup
  EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(2u, mesh_.n_faces() )    << "Wrong number of faces";

}

/* Adds a quad to a polymesh (should be a quad afterwards)
 */
TEST_F(OpenMeshAddFacePolyMesh, AddQuadToPolymesh) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[4];

  vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
  vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
  vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));

  // Add two faces
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);

  mesh_.add_face(face_vhandles);

  // Test setup:
  //  1 === 2
  //  |     |
  //  |     |
  //  |     |
  //  0 === 3

  // Check setup
  EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(1u, mesh_.n_faces() )    << "Wrong number of faces";

}

#endif // INCLUDE GUARD
<commit_msg>Added a Unittest for creating a cube with 6 quads in a poly mesh<commit_after>#ifndef INCLUDE_UNITTESTS_OpenMeshAddFaceTriangleMesh_HH
#define INCLUDE_UNITTESTS_OpenMeshAddFaceTriangleMesh_HH

#include <gtest/gtest.h>
#include <Unittests/unittests_common.hh>
#include <iostream>

class OpenMeshAddFaceTriangleMesh : public OpenMeshBase {

    protected:

        // This function is called before each test is run
        virtual void SetUp() {

            // Do some initial stuff with the member data here...
        }

        // This function is called after all tests are through
        virtual void TearDown() {

            // Do some final stuff with the member data here...
        }

    // Member already defined in OpenMeshBase
    //Mesh mesh_;
};

class OpenMeshAddFacePolyMesh : public OpenMeshBasePoly {

    protected:

        // This function is called before each test is run
        virtual void SetUp() {

            // Do some initial stuff with the member data here...
        }

        // This function is called after all tests are through
        virtual void TearDown() {

            // Do some final stuff with the member data here...
        }

    // Member already defined in OpenMeshBase
    //Mesh mesh_;
};

/*
 * ====================================================================
 * Define tests below
 * ====================================================================
 */

/* Adds two triangles to a tri mesh
 */
TEST_F(OpenMeshAddFaceTriangleMesh, AddTrianglesToTrimesh) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[4];

  vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
  vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
  vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));

  // Add two faces
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[0]);

  mesh_.add_face(face_vhandles);

  face_vhandles.clear();

  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[3]);
  mesh_.add_face(face_vhandles);

  // Test setup:
  //  1 === 2
  //  |   / |
  //  |  /  |
  //  | /   |
  //  0 === 3

  // Check setup
  EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(2u, mesh_.n_faces() )    << "Wrong number of faces";

}

/* Adds a quad to a trimesh (should be triangulated afterwards)
 */
TEST_F(OpenMeshAddFaceTriangleMesh, AddQuadToTrimesh) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[4];

  vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
  vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
  vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));

  // Add two faces
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);

  mesh_.add_face(face_vhandles);

  // Test setup:
  //  1 === 2
  //  |   / |
  //  |  /  |
  //  | /   |
  //  0 === 3

  // Check setup
  EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(2u, mesh_.n_faces() )    << "Wrong number of faces";

}

/* Adds a quad to a polymesh (should be a quad afterwards)
 */
TEST_F(OpenMeshAddFacePolyMesh, AddQuadToPolymesh) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[4];

  vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
  vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
  vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
  vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));

  // Add two faces
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);

  mesh_.add_face(face_vhandles);

  // Test setup:
  //  1 === 2
  //  |     |
  //  |     |
  //  |     |
  //  0 === 3

  // Check setup
  EXPECT_EQ(4u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(1u, mesh_.n_faces() )    << "Wrong number of faces";

}

/* Adds a quad to a polymesh (should be a quad afterwards)
 */
TEST_F(OpenMeshAddFacePolyMesh, CreatePolyMeshCube) {

  mesh_.clear();

  // Add some vertices
  Mesh::VertexHandle vhandle[8];
  vhandle[0] = mesh_.add_vertex(PolyMesh::Point(-1, -1,  1));
  vhandle[1] = mesh_.add_vertex(PolyMesh::Point( 1, -1,  1));
  vhandle[2] = mesh_.add_vertex(PolyMesh::Point( 1,  1,  1));
  vhandle[3] = mesh_.add_vertex(PolyMesh::Point(-1,  1,  1));
  vhandle[4] = mesh_.add_vertex(PolyMesh::Point(-1, -1, -1));
  vhandle[5] = mesh_.add_vertex(PolyMesh::Point( 1, -1, -1));
  vhandle[6] = mesh_.add_vertex(PolyMesh::Point( 1,  1, -1));
  vhandle[7] = mesh_.add_vertex(PolyMesh::Point(-1,  1, -1));

  // Add six faces to form a cube
  std::vector<Mesh::VertexHandle> face_vhandles;

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[3]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[7]);
  face_vhandles.push_back(vhandle[6]);
  face_vhandles.push_back(vhandle[5]);
  face_vhandles.push_back(vhandle[4]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[4]);
  face_vhandles.push_back(vhandle[5]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[1]);
  face_vhandles.push_back(vhandle[5]);
  face_vhandles.push_back(vhandle[6]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[3]);
  face_vhandles.push_back(vhandle[2]);
  face_vhandles.push_back(vhandle[6]);
  face_vhandles.push_back(vhandle[7]);
  mesh_.add_face(face_vhandles);

  face_vhandles.clear();
  face_vhandles.push_back(vhandle[0]);
  face_vhandles.push_back(vhandle[3]);
  face_vhandles.push_back(vhandle[7]);
  face_vhandles.push_back(vhandle[4]);
  mesh_.add_face(face_vhandles);

  // Test setup:
  //
  //
  //    3 ======== 2
  //   /          /|
  //  /          / |      z
  // 0 ======== 1  |      |
  // |          |  |      |   y
  // |  7       |  6      |  /
  // |          | /       | /
  // |          |/        |/
  // 4 ======== 5         -------> x
  //

  // Check setup
  EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices";
  EXPECT_EQ(6u, mesh_.n_faces() )    << "Wrong number of faces";

}

#endif // INCLUDE GUARD
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkMeshQuality.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkMeshQuality.h"

#include "vtkCellData.h"
#include "vtkDataSet.h"
#include "vtkFieldData.h"
#include "vtkFloatArray.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkTetra.h"

vtkCxxRevisionMacro(vtkMeshQuality, "1.6");
vtkStandardNewMacro(vtkMeshQuality);

//----------------------------------------------------------------------------
// Constructor
vtkMeshQuality::vtkMeshQuality()
{
 this->GeometryOff();
 this->TopologyOff();
 this->FieldDataOff();
 this->PointDataOff();
 this->CellDataOn();

 this->Volume = 1;
 this->Ratio = 1;
}

//----------------------------------------------------------------------------
//destructor
vtkMeshQuality::~vtkMeshQuality()
{
}

//----------------------------------------------------------------------------
void vtkMeshQuality::Execute()
{
  int j;
  vtkDataSet *input = this->GetInput();
  vtkIdType numCells=input->GetNumberOfCells();
  vtkIdList *id = vtkIdList::New();
  vtkCellData *celld = vtkCellData::New();
  vtkFloatArray *scalars = vtkFloatArray::New();
  if (this->Volume && this->Ratio)
    {
    scalars->SetNumberOfComponents(2);
    }
  scalars->SetNumberOfTuples(numCells);

  double p1[3],p2[3],p3[3],p4[3];
  double dp1[3],dp2[3],dp3[3],dp4[3];
  double volume, ratio;
  double incenter[3], circenter[3];

  for (j=0; j<numCells; j++)
    {
    input->GetCellPoints(j,id);
    input->GetPoint(id->GetId(0),p1);
    dp1[0]=p1[0]; dp1[1]=p1[1]; dp1[2]=p1[2];
    input->GetPoint(id->GetId(1),p2);
    dp2[0]=p2[0]; dp2[1]=p2[1]; dp2[2]=p2[2];
    input->GetPoint(id->GetId(2),p3);
    dp3[0]=p3[0]; dp3[1]=p3[1]; dp3[2]=p3[2];
    input->GetPoint(id->GetId(3),p4);
    dp4[0]=p4[0]; dp4[1]=p4[1]; dp4[2]=p4[2];

    if (this->Volume && this->Ratio)
      {
      volume = fabs(vtkTetra::ComputeVolume(dp1,dp2,dp3,dp4));
      ratio = sqrt(vtkTetra::Circumsphere(dp1,dp2,dp3,dp4, circenter))/\
        vtkTetra::Insphere(dp1,dp2,dp3,dp4,incenter);

      ratio = ratio/3;

      scalars->SetTuple2(j,volume,ratio);
      }
    else if (this->Ratio)
      {
      ratio = sqrt(vtkTetra::Circumsphere(dp1,dp2,dp3,dp4, circenter))/\
        vtkTetra::Insphere(dp1,dp2,dp3,dp4,incenter);
      ratio = ratio/3;
      scalars->SetTuple1(j,ratio);
      }
    else if (this->Volume)
      {
      volume = fabs(vtkTetra::ComputeVolume(dp1,dp2,dp3,dp4));
      scalars->SetTuple1(j,volume);
      }
    else
      {
      vtkErrorMacro(<<"Nothing to be calculated!!!!");
      }
    }

  int idx = celld->AddArray(scalars);
  celld->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
  this->GetOutput()->SetFieldData(celld);
  celld->Delete();
  id->Delete();
  scalars->Delete();
}

//----------------------------------------------------------------------------
void vtkMeshQuality::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToDataObjectFilter::PrintSelf(os,indent);

  os << indent << "Input: " << this->GetInput() << "\n";
  os << indent << "Volume: " << (this->Volume ? "On\n" : "Off\n");
  os << indent << "Ratio: " << (this->Ratio ? "On\n" : "Off\n");
}
<commit_msg>STYLE: Suggested by Philippe P. Pebay<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMeshQuality.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkMeshQuality.h"

#include "vtkCellData.h"
#include "vtkDataSet.h"
#include "vtkFieldData.h"
#include "vtkFloatArray.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkTetra.h"

vtkCxxRevisionMacro(vtkMeshQuality, "1.7");
vtkStandardNewMacro(vtkMeshQuality);

//----------------------------------------------------------------------------
// Constructor
vtkMeshQuality::vtkMeshQuality()
{
 this->GeometryOff();
 this->TopologyOff();
 this->FieldDataOff();
 this->PointDataOff();
 this->CellDataOn();

 this->Volume = 1;
 this->Ratio = 1;
}

//----------------------------------------------------------------------------
//destructor
vtkMeshQuality::~vtkMeshQuality()
{
}

//----------------------------------------------------------------------------
void vtkMeshQuality::Execute()
{
  int j;
  vtkDataSet *input = this->GetInput();
  vtkIdType numCells=input->GetNumberOfCells();
  vtkIdList *id = vtkIdList::New();
  vtkCellData *celld = vtkCellData::New();
  vtkFloatArray *scalars = vtkFloatArray::New();
  if (this->Volume && this->Ratio)
    {
    scalars->SetNumberOfComponents(2);
    }
  scalars->SetNumberOfTuples(numCells);

  double dp1[3],dp2[3],dp3[3],dp4[3];
  double volume, ratio;
  double incenter[3], circenter[3];

  for (j=0; j<numCells; j++)
    {
    input->GetCellPoints(j,id);
    input->GetPoint(id->GetId(0),dp1);
    input->GetPoint(id->GetId(1),dp2);
    input->GetPoint(id->GetId(2),dp3);
    input->GetPoint(id->GetId(3),dp4);

    if (this->Volume && this->Ratio)
      {
      volume = fabs(vtkTetra::ComputeVolume(dp1,dp2,dp3,dp4));
      ratio = sqrt(vtkTetra::Circumsphere(dp1,dp2,dp3,dp4, circenter))/\
        vtkTetra::Insphere(dp1,dp2,dp3,dp4,incenter);

      ratio = ratio/3;

      scalars->SetTuple2(j,volume,ratio);
      }
    else if (this->Ratio)
      {
      ratio = sqrt(vtkTetra::Circumsphere(dp1,dp2,dp3,dp4, circenter))/\
        vtkTetra::Insphere(dp1,dp2,dp3,dp4,incenter);
      ratio = ratio/3;
      scalars->SetTuple1(j,ratio);
      }
    else if (this->Volume)
      {
      volume = fabs(vtkTetra::ComputeVolume(dp1,dp2,dp3,dp4));
      scalars->SetTuple1(j,volume);
      }
    else
      {
      vtkErrorMacro(<<"Nothing to be calculated!!!!");
      }
    }

  int idx = celld->AddArray(scalars);
  celld->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
  this->GetOutput()->SetFieldData(celld);
  celld->Delete();
  id->Delete();
  scalars->Delete();
}

//----------------------------------------------------------------------------
void vtkMeshQuality::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToDataObjectFilter::PrintSelf(os,indent);

  os << indent << "Input: " << this->GetInput() << "\n";
  os << indent << "Volume: " << (this->Volume ? "On\n" : "Off\n");
  os << indent << "Ratio: " << (this->Ratio ? "On\n" : "Off\n");
}
<|endoftext|>


<commit_before>#include "alsa.hpp"
#include <audio_io/audio_io.hpp>
#include <audio_io/private/audio_outputs.hpp>
#include <audio_io/private/sample_format_converter.hpp>
#include <vector>
#include <string>
#include <functional>
#include <thread>
#include <atomic>
#include <algorithm>
#include <alsa/asoundlib.h>

namespace audio_io {
namespace implementation {

AlsaOutputDevice::AlsaOutputDevice(std::function<void(float*, int)> callback, std::string name, int sr, int channels, int blockSize, float minLatency, float startLatency, float maxLatency) {
	snd_pcm_hw_params_t *params;
	snd_pcm_sw_params_t *params_sw;
	snd_pcm_hw_params_alloca(&params);
	snd_pcm_sw_params_alloca(&params_sw);
	int res = snd_pcm_open(&device_handle, name.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
	if(res) {
		throw AudioIOError("An Alsa Error occurred.");
	}
	res = snd_pcm_hw_params_any(device_handle, params);
	if(res < 0) {
		throw AudioIOError("Alsa: could not configuer PCM device.");
	}
	//TODO: this doesn't deal with endianness properly, and uses our knowledge that x86 is little endian.
	res = snd_pcm_hw_params_set_format(device_handle, params, SND_PCM_FORMAT_FLOAT_LE);
	if(res < 0) {
		throw AudioIOError("ALSA: Couldn't get little endian float.");
	}
	unsigned int alsaChannels = channels;
	res = snd_pcm_hw_params_set_channels_near (device_handle, params, &alsaChannels);
	if(res < 0) {
		throw AudioIOError("Couldn't constrain channel count.");
	}
	unsigned int alsaSr = sr;
	res = snd_pcm_hw_params_set_rate_near(device_handle, params, &alsaSr, 0);
	if(res < 0) {
		throw AudioIOError("ALSA: Couldn't constrain sample rate.");
	}
	res = snd_pcm_hw_params_set_access(device_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
	if(res < 0) {
		throw AudioIOError("ALSA: couldn't set access.");
	}
	//Use 10 milliseconds (1 ms = 1000 us).
	//No app is likely to go below this, nor should we.
	unsigned int alsaPeriodMicrosecs = 10000;
	res = snd_pcm_hw_params_set_period_time_near(device_handle, params, &alsaPeriodMicrosecs, 0);
	if(res < 0) {
		throw AudioIOError("ALSA: couldn't configure period time.");
	}
	//compute needed buffer size and bump maxLatency if needed.
	maxLatency = std::max<double>(maxLatency, 2.3*blockSize/(double)sr);
	snd_pcm_uframes_t alsaBufferSize = alsaSr*maxLatency;
	res = snd_pcm_hw_params_set_buffer_size_near(device_handle, params, &alsaBufferSize);
	if(res < 0) {
		throw AudioIOError("ALSA: couldn't set buffer size.");
	}
	res = snd_pcm_hw_params(device_handle, params);
	if(res < 0) {
		throw AudioIOError("ALSA: Could not prepare device.");
	}
	//Software parameter setup.
	res = snd_pcm_sw_params_current(device_handle, params_sw);
	if(res < 0) {
		throw AudioIOError("ALSA: couldn't get current software parameters.");
	}
	//Start the device when the buffer is 90% full.
	res = snd_pcm_sw_params_set_start_threshold(device_handle, params_sw, (snd_pcm_uframes_t)(0.9*alsaBufferSize));
	if(res < 0) {
		throw AudioIOError("ALSA: couldn't set startup threshold.");
	}
	res = snd_pcm_sw_params(device_handle, params_sw);
	if(res < 0) {
		throw AudioIOError("ALSA: couldn't install software params.");
	}
	init(callback, blockSize, channels, sr, (int)alsaChannels, (int)alsaSr);
	worker_running.test_and_set();
	worker_thread = std::thread([&] () {workerThreadFunction();});
}

AlsaOutputDevice::~AlsaOutputDevice() {
	stop();
}

void AlsaOutputDevice::stop() {
	if(stopped == false) {
		if(worker_thread.joinable()) {
			worker_running.clear();
			worker_thread.join();
		}
	}
	stopped = true;
}

void AlsaOutputDevice::workerThreadFunction() {
	float* buffer = new float[output_channels*output_frames]();
	while(worker_running.test_and_set()) {
		sample_format_converter->write(output_frames, buffer);
		snd_pcm_sframes_t res = snd_pcm_writei(device_handle, buffer, (snd_pcm_uframes_t)output_frames);
		if(res < 0) {
			snd_pcm_prepare(device_handle);
		}
	}
	snd_pcm_drain(device_handle);
	snd_pcm_close(device_handle);
	delete[] buffer;
}

}
}<commit_msg>Hypothetically support surround sound properly on ALSA.  Only time can tell if this works.<commit_after>#include "alsa.hpp"
#include <audio_io/audio_io.hpp>
#include <audio_io/private/audio_outputs.hpp>
#include <audio_io/private/sample_format_converter.hpp>
#include <vector>
#include <string>
#include <functional>
#include <thread>
#include <atomic>
#include <algorithm>
#include <alsa/asoundlib.h>

namespace audio_io {
namespace implementation {

AlsaOutputDevice::AlsaOutputDevice(std::function<void(float*, int)> callback, std::string name, int sr, int channels, int blockSize, float minLatency, float startLatency, float maxLatency) {
	snd_pcm_hw_params_t *params;
	snd_pcm_sw_params_t *params_sw;
	snd_pcm_hw_params_alloca(&params);
	snd_pcm_sw_params_alloca(&params_sw);
	int res = snd_pcm_open(&device_handle, name.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
	if(res) {
		throw AudioIOError("An Alsa Error occurred.");
	}
	res = snd_pcm_hw_params_any(device_handle, params);
	if(res < 0) {
		throw AudioIOError("Alsa: could not configuer PCM device.");
	}
	//TODO: this doesn't deal with endianness properly, and uses our knowledge that x86 is little endian.
	res = snd_pcm_hw_params_set_format(device_handle, params, SND_PCM_FORMAT_FLOAT_LE);
	if(res < 0) {
		throw AudioIOError("ALSA: Couldn't get little endian float.");
	}
	unsigned int alsaChannels = channels;
	res = snd_pcm_hw_params_set_channels_near (device_handle, params, &alsaChannels);
	if(res < 0) {
		throw AudioIOError("Couldn't constrain channel count.");
	}
	unsigned int alsaSr = sr;
	res = snd_pcm_hw_params_set_rate_near(device_handle, params, &alsaSr, 0);
	if(res < 0) {
		throw AudioIOError("ALSA: Couldn't constrain sample rate.");
	}
	res = snd_pcm_hw_params_set_access(device_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
	if(res < 0) {
		throw AudioIOError("ALSA: couldn't set access.");
	}
	//Use 10 milliseconds (1 ms = 1000 us).
	//No app is likely to go below this, nor should we.
	unsigned int alsaPeriodMicrosecs = 10000;
	res = snd_pcm_hw_params_set_period_time_near(device_handle, params, &alsaPeriodMicrosecs, 0);
	if(res < 0) {
		throw AudioIOError("ALSA: couldn't configure period time.");
	}
	//compute needed buffer size and bump maxLatency if needed.
	maxLatency = std::max<double>(maxLatency, 2.3*blockSize/(double)sr);
	snd_pcm_uframes_t alsaBufferSize = alsaSr*maxLatency;
	res = snd_pcm_hw_params_set_buffer_size_near(device_handle, params, &alsaBufferSize);
	if(res < 0) {
		throw AudioIOError("ALSA: couldn't set buffer size.");
	}
	res = snd_pcm_hw_params(device_handle, params);
	if(res < 0) {
		throw AudioIOError("ALSA: Could not prepare device.");
	}
	//Software parameter setup.
	res = snd_pcm_sw_params_current(device_handle, params_sw);
	if(res < 0) {
		throw AudioIOError("ALSA: couldn't get current software parameters.");
	}
	//Start the device when the buffer is 90% full.
	res = snd_pcm_sw_params_set_start_threshold(device_handle, params_sw, (snd_pcm_uframes_t)(0.9*alsaBufferSize));
	if(res < 0) {
		throw AudioIOError("ALSA: couldn't set startup threshold.");
	}
	res = snd_pcm_sw_params(device_handle, params_sw);
	if(res < 0) {
		throw AudioIOError("ALSA: couldn't install software params.");
	}
	init(callback, blockSize, channels, sr, (int)alsaChannels, (int)alsaSr);
	worker_running.test_and_set();
	worker_thread = std::thread([&] () {workerThreadFunction();});
}

AlsaOutputDevice::~AlsaOutputDevice() {
	stop();
}

void AlsaOutputDevice::stop() {
	if(stopped == false) {
		if(worker_thread.joinable()) {
			worker_running.clear();
			worker_thread.join();
		}
	}
	stopped = true;
}

void AlsaOutputDevice::workerThreadFunction() {
	float* buffer = new float[output_channels*output_frames]();
	while(worker_running.test_and_set()) {
		sample_format_converter->write(output_frames, buffer);
		//If we're 5.1 or 7.1, we need to swap the channels around to match Linux's idea of surround sound.
		//The stuff herer comes from http://drona.csa.iisc.ernet.in/~uday/alsamch.shtml
		//If this doesn't work, there is an ALSA channel mapping API.
		if(output_channels == 6 || output_channels == 8) {
			const int initial_center = 2, initial_lfe = 3;
			const int new_center = output_channels-2, new_lfe = output_channels-1;
			for(int i = 0; i < output_frames*output_channels; i+= output_channels) {
				std::swap(buffer[i+initial_center], buffer[i+new_center]);
				std::swap(buffer[i+initial_lfe], buffer[i+new_lfe]);
			}
		}
		snd_pcm_sframes_t res = snd_pcm_writei(device_handle, buffer, (snd_pcm_uframes_t)output_frames);
		if(res < 0) {
			snd_pcm_prepare(device_handle);
		}
	}
	snd_pcm_drain(device_handle);
	snd_pcm_close(device_handle);
	delete[] buffer;
}

}
}<|endoftext|>


<commit_before>/// @file
/// @version 3.4
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#ifdef _SDL
//#include <SDL/SDL.h>

#include <hltypes/hltypesUtil.h>

#include "Buffer.h"
#include "SDL_AudioManager.h"
#include "SDL_Player.h"
#include "Sound.h"
#include "xal.h"

namespace xal
{
	SDL_Player::SDL_Player(Sound* sound) : Player(sound), playing(false),
		position(0), currentGain(1.0f), readPosition(0), writePosition(0)
	{
		memset(this->circleBuffer, 0, STREAM_BUFFER * sizeof(unsigned char));
	}

	SDL_Player::~SDL_Player()
	{
		// AudioManager calls _stop before destruction
	}

	void SDL_Player::_getData(int size, unsigned char** data1, int* size1, unsigned char** data2, int* size2)
	{
		if (!this->sound->isStreamed())
		{
			int streamSize = this->buffer->load(this->looping, size);
			if (streamSize == 0)
			{
				*data1 = NULL;
				*size1 = 0;
				*data2 = NULL;
				*size2 = 0;
				return;
			}
			hstream& stream = this->buffer->getStream();
			*data1 = (unsigned char*)&stream[this->readPosition];
			*size1 = hmin(hmin(streamSize, streamSize - this->readPosition), size);
			*data2 = NULL;
			*size2 = 0;
			if (this->looping && this->readPosition + size > streamSize)
			{
				*data2 = (unsigned char*)stream;
				*size2 = size - *size1;
				this->readPosition = (this->readPosition + size) % streamSize;
			}
			else
			{
				this->readPosition = hmin(this->readPosition + size, streamSize);
			}
			return;
		}
		*data1 = &this->circleBuffer[this->readPosition];
		*size1 = size;
		*data2 = NULL;
		*size2 = 0;
		if (this->readPosition + size > STREAM_BUFFER)
		{
			*size1 = STREAM_BUFFER - this->readPosition;
			*data2 = this->circleBuffer;
			*size2 = size - *size1;
		}
		this->readPosition = (this->readPosition + size) % STREAM_BUFFER;
	}

	void SDL_Player::_update(float timeDelta)
	{
		Player::_update(timeDelta);
		// making sure a corrected size is used
		int size = this->buffer->calcOutputSize(this->buffer->getSize());
		if (size > 0 && this->position >= size)
		{
			if (this->looping)
			{
				this->position -= this->position / size * size;
			}
			else if (this->playing)
			{
				this->_stop();
			}
		}
	}

	bool SDL_Player::mixAudio(hstream& stream, int size, bool first)
	{
		if (!this->playing)
		{
			return false;
		}
		unsigned char* data1 = NULL;
		int size1 = 0;
		unsigned char* data2 = NULL;
		int size2 = 0;
		this->_getData(size, &data1, &size1, &data2, &size2); // ironically this is very similar to how DirectSound does things internally
		if (size1 > 0)
		{
			if (first && this->currentGain == 1.0f)
			{
				memcpy((unsigned char*)stream, data1, size1);
				if (size2 > 0)
				{
					memcpy((void*)&stream[size1], data2, size2);
				}
			}
			else
			{
				short* sStream = (short*)(unsigned char*)stream;
				short* sData1 = (short*)data1;
				short* sData2 = (short*)data2;
				size1 = size1 * sizeof(unsigned char) / sizeof(short);
				size2 = size2 * sizeof(unsigned char) / sizeof(short);
				if (!first)
				{
					for_iter (i, 0, size1)
					{
						sStream[i] = (short)hclamp((int)(sStream[i] + this->currentGain * sData1[i]), -32768, 32767);
					}
					for_iter (i, 0, size2)
					{
						sStream[size1 + i] = (short)hclamp((int)(sStream[size1 + i] + this->currentGain * sData2[i]), -32768, 32767);
					}
				}
				else
				{
					for_iter (i, 0, size1)
					{
						sStream[i] = (short)(sData1[i] * this->currentGain);
					}
					for_iter (i, 0, size2)
					{
						sStream[size1 + i] = (short)(sData2[i] * this->currentGain);
					}
				}
			}
			this->position += size1 + size2;
		}
		return true;
	}

	unsigned int SDL_Player::_systemGetBufferPosition()
	{
		int count = 0;
		if (this->readPosition > this->writePosition)
		{
			count = (this->readPosition - this->writePosition);
		}
		else if (this->readPosition < this->writePosition)
		{
			count = (STREAM_BUFFER - this->writePosition + this->readPosition);
		}
		return this->buffer->calcInputSize(count);
	}

	float SDL_Player::_systemGetOffset()
	{
		return this->offset;
	}

	void SDL_Player::_systemSetOffset(float value)
	{
		this->offset = value;
	}

	bool SDL_Player::_systemPreparePlay()
	{
		return true;
	}

	void SDL_Player::_systemPrepareBuffer()
	{
		if (!this->sound->isStreamed())
		{
			this->buffer->load(this->looping, this->buffer->getSize());
			return;
		}
		if (!this->paused)
		{
			this->readPosition = 0;
			this->writePosition = 0;
			int size = this->_fillBuffer(STREAM_BUFFER);
			if (size < STREAM_BUFFER)
			{
				memset(&this->circleBuffer[size], 0, (STREAM_BUFFER - size) * sizeof(unsigned char));
			}
		}
	}

	void SDL_Player::_systemUpdateGain()
	{
		this->currentGain = this->_calcGain();
	}

	void SDL_Player::_systemPlay()
	{
		this->playing = true;
	}

	int SDL_Player::_systemStop()
	{
		this->playing = false;
		if (!this->paused)
		{
			this->position = 0;
			this->readPosition = 0;
			this->writePosition = 0;
			this->buffer->rewind();
		}
		return 0;
	}

	int SDL_Player::_systemUpdateStream()
	{
		int result = 0;
		int count = 0;
		if (this->readPosition > this->writePosition)
		{
			count = (this->readPosition - this->writePosition) / STREAM_BUFFER_SIZE;
		}
		else if (this->readPosition < this->writePosition)
		{
			count = (STREAM_BUFFER - this->writePosition + this->readPosition) / STREAM_BUFFER_SIZE;
		}
		if (count > 0)
		{
			result = this->_fillBuffer(count * STREAM_BUFFER_SIZE);
			result = this->buffer->calcInputSize(result);
		}
		return result;
	}

	int SDL_Player::_fillBuffer(int size)
	{
		// making sure the buffer doesn't overflow since upsampling can cause that
		size = this->buffer->calcInputSize(size);
		// load the data from the buffer
		int streamSize = this->buffer->load(this->looping, size);
		hstream& stream = this->buffer->getStream();
		if (this->writePosition + streamSize <= STREAM_BUFFER)
		{
			memcpy(&this->circleBuffer[this->writePosition], (unsigned char*)stream, streamSize * sizeof(unsigned char));
		}
		else
		{
			int remaining = STREAM_BUFFER - this->writePosition;
			memcpy(&this->circleBuffer[this->writePosition], (unsigned char*)stream, remaining * sizeof(unsigned char));
			memcpy(this->circleBuffer, (unsigned char*)stream, (streamSize - remaining) * sizeof(unsigned char));
		}
		this->writePosition = (this->writePosition + streamSize) % STREAM_BUFFER;
		if (!this->looping && streamSize < size) // fill with silence if source is at the end
		{
			streamSize = size - streamSize;
			if (this->writePosition + streamSize <= STREAM_BUFFER)
			{
				memset(&this->circleBuffer[this->writePosition], 0, streamSize * sizeof(unsigned char));
			}
			else
			{
				int remaining = STREAM_BUFFER - this->writePosition;
				memset(&this->circleBuffer[this->writePosition], 0, remaining * sizeof(unsigned char));
				memset(this->circleBuffer, 0, (streamSize - remaining) * sizeof(unsigned char));
			}
			this->writePosition = (this->writePosition + streamSize) % STREAM_BUFFER;
			streamSize = size;
		}
		return streamSize;
	}

}
#endif<commit_msg>- fixed a bug in SDL_Player with the circular buffer<commit_after>/// @file
/// @version 3.4
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#ifdef _SDL
//#include <SDL/SDL.h>

#include <hltypes/hltypesUtil.h>

#include "Buffer.h"
#include "SDL_AudioManager.h"
#include "SDL_Player.h"
#include "Sound.h"
#include "xal.h"

namespace xal
{
	SDL_Player::SDL_Player(Sound* sound) : Player(sound), playing(false),
		position(0), currentGain(1.0f), readPosition(0), writePosition(0)
	{
		memset(this->circleBuffer, 0, STREAM_BUFFER * sizeof(unsigned char));
	}

	SDL_Player::~SDL_Player()
	{
		// AudioManager calls _stop before destruction
	}

	void SDL_Player::_getData(int size, unsigned char** data1, int* size1, unsigned char** data2, int* size2)
	{
		if (!this->sound->isStreamed())
		{
			int streamSize = this->buffer->load(this->looping, size);
			if (streamSize == 0)
			{
				*data1 = NULL;
				*size1 = 0;
				*data2 = NULL;
				*size2 = 0;
				return;
			}
			hstream& stream = this->buffer->getStream();
			*data1 = (unsigned char*)&stream[this->readPosition];
			*size1 = hmin(hmin(streamSize, streamSize - this->readPosition), size);
			*data2 = NULL;
			*size2 = 0;
			if (this->looping && this->readPosition + size > streamSize)
			{
				*data2 = (unsigned char*)stream;
				*size2 = size - *size1;
				this->readPosition = (this->readPosition + size) % streamSize;
			}
			else
			{
				this->readPosition = hmin(this->readPosition + size, streamSize);
			}
			return;
		}
		*data1 = &this->circleBuffer[this->readPosition];
		*size1 = size;
		*data2 = NULL;
		*size2 = 0;
		if (this->readPosition + size > STREAM_BUFFER)
		{
			*size1 = STREAM_BUFFER - this->readPosition;
			*data2 = this->circleBuffer;
			*size2 = size - *size1;
		}
		this->readPosition = (this->readPosition + size) % STREAM_BUFFER;
	}

	void SDL_Player::_update(float timeDelta)
	{
		Player::_update(timeDelta);
		// making sure a corrected size is used
		int size = this->buffer->calcOutputSize(this->buffer->getSize());
		if (size > 0 && this->position >= size)
		{
			if (this->looping)
			{
				this->position -= this->position / size * size;
			}
			else if (this->playing)
			{
				this->_stop();
			}
		}
	}

	bool SDL_Player::mixAudio(hstream& stream, int size, bool first)
	{
		if (!this->playing)
		{
			return false;
		}
		unsigned char* data1 = NULL;
		int size1 = 0;
		unsigned char* data2 = NULL;
		int size2 = 0;
		this->_getData(size, &data1, &size1, &data2, &size2); // ironically this is very similar to how DirectSound does things internally
		if (size1 > 0)
		{
			if (first && this->currentGain == 1.0f)
			{
				memcpy((unsigned char*)stream, data1, size1);
				if (size2 > 0)
				{
					memcpy((void*)&stream[size1], data2, size2);
				}
			}
			else
			{
				short* sStream = (short*)(unsigned char*)stream;
				short* sData1 = (short*)data1;
				short* sData2 = (short*)data2;
				size1 = size1 * sizeof(unsigned char) / sizeof(short);
				size2 = size2 * sizeof(unsigned char) / sizeof(short);
				if (!first)
				{
					for_iter (i, 0, size1)
					{
						sStream[i] = (short)hclamp((int)(sStream[i] + this->currentGain * sData1[i]), -32768, 32767);
					}
					for_iter (i, 0, size2)
					{
						sStream[size1 + i] = (short)hclamp((int)(sStream[size1 + i] + this->currentGain * sData2[i]), -32768, 32767);
					}
				}
				else
				{
					for_iter (i, 0, size1)
					{
						sStream[i] = (short)(sData1[i] * this->currentGain);
					}
					for_iter (i, 0, size2)
					{
						sStream[size1 + i] = (short)(sData2[i] * this->currentGain);
					}
				}
			}
			this->position += size1 + size2;
		}
		return true;
	}

	unsigned int SDL_Player::_systemGetBufferPosition()
	{
		int count = 0;
		if (this->readPosition > this->writePosition)
		{
			count = (this->readPosition - this->writePosition);
		}
		else if (this->readPosition < this->writePosition)
		{
			count = (STREAM_BUFFER - this->writePosition + this->readPosition);
		}
		return this->buffer->calcInputSize(count);
	}

	float SDL_Player::_systemGetOffset()
	{
		return this->offset;
	}

	void SDL_Player::_systemSetOffset(float value)
	{
		this->offset = value;
	}

	bool SDL_Player::_systemPreparePlay()
	{
		return true;
	}

	void SDL_Player::_systemPrepareBuffer()
	{
		if (!this->sound->isStreamed())
		{
			this->buffer->load(this->looping, this->buffer->getSize());
			return;
		}
		if (!this->paused)
		{
			this->readPosition = 0;
			this->writePosition = 0;
			int size = this->_fillBuffer(STREAM_BUFFER);
			if (size < STREAM_BUFFER)
			{
				memset(&this->circleBuffer[size], 0, (STREAM_BUFFER - size) * sizeof(unsigned char));
			}
		}
	}

	void SDL_Player::_systemUpdateGain()
	{
		this->currentGain = this->_calcGain();
	}

	void SDL_Player::_systemPlay()
	{
		this->playing = true;
	}

	int SDL_Player::_systemStop()
	{
		this->playing = false;
		if (!this->paused)
		{
			this->position = 0;
			this->readPosition = 0;
			this->writePosition = 0;
			this->buffer->rewind();
		}
		return 0;
	}

	int SDL_Player::_systemUpdateStream()
	{
		int result = 0;
		int count = 0;
		if (this->readPosition > this->writePosition)
		{
			count = (this->readPosition - this->writePosition) / STREAM_BUFFER_SIZE;
		}
		else if (this->readPosition < this->writePosition)
		{
			count = (STREAM_BUFFER - this->writePosition + this->readPosition) / STREAM_BUFFER_SIZE;
		}
		if (count > 0)
		{
			result = this->_fillBuffer(count * STREAM_BUFFER_SIZE);
			result = this->buffer->calcInputSize(result);
		}
		return result;
	}

	int SDL_Player::_fillBuffer(int size)
	{
		// making sure the buffer doesn't overflow since upsampling can cause that
		size = this->buffer->calcInputSize(size);
		// load the data from the buffer
		int streamSize = this->buffer->load(this->looping, size);
		hstream& stream = this->buffer->getStream();
		if (this->writePosition + streamSize <= STREAM_BUFFER)
		{
			memcpy(&this->circleBuffer[this->writePosition], (unsigned char*)stream, streamSize * sizeof(unsigned char));
		}
		else
		{
			int remaining = STREAM_BUFFER - this->writePosition;
			memcpy(&this->circleBuffer[this->writePosition], &stream[0], remaining * sizeof(unsigned char));
			memcpy(this->circleBuffer, &stream[remaining], (streamSize - remaining) * sizeof(unsigned char));
		}
		this->writePosition = (this->writePosition + streamSize) % STREAM_BUFFER;
		if (!this->looping && streamSize < size) // fill with silence if source is at the end
		{
			streamSize = size - streamSize;
			if (this->writePosition + streamSize <= STREAM_BUFFER)
			{
				memset(&this->circleBuffer[this->writePosition], 0, streamSize * sizeof(unsigned char));
			}
			else
			{
				int remaining = STREAM_BUFFER - this->writePosition;
				memset(&this->circleBuffer[this->writePosition], 0, remaining * sizeof(unsigned char));
				memset(this->circleBuffer, 0, (streamSize - remaining) * sizeof(unsigned char));
			}
			this->writePosition = (this->writePosition + streamSize) % STREAM_BUFFER;
			streamSize = size;
		}
		return streamSize;
	}

}
#endif<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 *
 * aries_proxy.cpp
 * file description
 *
 * Copyright(c) 2015, CMU
 *
 * /peloton/src/backend/logging/aries_proxy.cpp
 *
 *-------------------------------------------------------------------------
 */

#include "backend/logging/aries_proxy.h"

#include <iostream> // cout
#include <unistd.h> // sleep

namespace peloton {
namespace logging {

void AriesProxy::logging_MainLoop() const{
  // TODO :: performance optimization
  for(int i=0;i<50;i++){
    sleep(5);
    printf("buffer size %u GetBufferSize() %d \n", buffer_size,(int) GetBufferSize());
    if( GetBufferSize() > buffer_size ) Flush();
  }
}

/**
 * @brief Recording log record
 * @param log record
 */
void AriesProxy::log(LogRecord record) const{
  aries_buffer_mutex.lock();
  aries_buffer.push_back(record);
  aries_buffer_mutex.unlock();
}

/**
 * @brief Get buffer size
 * @return return the size of buffer
 */
size_t AriesProxy::GetBufferSize() const{
  aries_buffer_mutex.lock();
  size_t size = aries_buffer.size();
  aries_buffer_mutex.unlock();
  return size;
}

/**
 * TODO ::
 * @brief flush all record, for now it's just printing out
 */
void AriesProxy::Flush() const{
  aries_buffer_mutex.lock();
  for( auto record : aries_buffer )
    std::cout << "record : " << record << std::endl;
  aries_buffer.clear();
  aries_buffer_mutex.unlock();
}

}  // namespace logging
}  // namespace peloton

<commit_msg>Minor update - use convenient wrapper<commit_after>/*-------------------------------------------------------------------------
 *
 * aries_proxy.cpp
 * file description
 *
 * Copyright(c) 2015, CMU
 *
 * /peloton/src/backend/logging/aries_proxy.cpp
 *
 *-------------------------------------------------------------------------
 */

#include "backend/logging/aries_proxy.h"

#include <iostream> // cout
#include <unistd.h> // sleep

namespace peloton {
namespace logging {

void AriesProxy::logging_MainLoop() const{
  // TODO :: performance optimization
  for(int i=0;i<50;i++){
    sleep(5);
    printf("buffer size %u GetBufferSize() %d \n", buffer_size,(int) GetBufferSize());
    if( GetBufferSize() > buffer_size ) Flush();
  }
}

/**
 * @brief Recording log record
 * @param log record
 */
void AriesProxy::log(LogRecord record) const{
  std::lock_guard<std::mutex> lock(aries_buffer_mutex);
  aries_buffer.push_back(record);
}

/**
 * @brief Get buffer size
 * @return return the size of buffer
 */
size_t AriesProxy::GetBufferSize() const{
  std::lock_guard<std::mutex> lock(aries_buffer_mutex);
  return aries_buffer.size();
}

/**
 * TODO ::
 * @brief flush all record, for now it's just printing out
 */
void AriesProxy::Flush() const{
  std::lock_guard<std::mutex> lock(aries_buffer_mutex);
  for( auto record : aries_buffer )
    std::cout << "record : " << record << std::endl;
  aries_buffer.clear();
}

}  // namespace logging
}  // namespace peloton

<|endoftext|>