<commit_before>/*
Copyright (c) 2015-2017 Advanced Micro Devices, Inc. All rights reserved.

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

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

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

/* HIT_START
 * BUILD: %t %s ../../test_common.cpp NVCC_OPTIONS --std=c++11
 * RUN: %t
 * HIT_END
 */

#include "hip/hip_runtime.h"
#include "test_common.h"

#ifdef __HIP_PLATFORM_HCC__
#include <hc_am.hpp>
#define USE_HCC_MEMTRACKER 0
#endif

int elementSizes[] = {16, 1024,524288};
int nSizes  = sizeof(elementSizes) / sizeof(int);

int enablePeers(int dev0, int dev1)
{
    int canAccessPeer01, canAccessPeer10;
    HIPCHECK(hipDeviceCanAccessPeer(&canAccessPeer01, dev0, dev1));
    HIPCHECK(hipDeviceCanAccessPeer(&canAccessPeer10, dev1, dev0));
    if (!canAccessPeer01 || !canAccessPeer10) {
        return -1;
    }

    HIPCHECK(hipSetDevice(dev0));
    HIPCHECK(hipDeviceEnablePeerAccess(dev1, 0/*flags*/));
    HIPCHECK(hipSetDevice(dev1));
    HIPCHECK(hipDeviceEnablePeerAccess(dev0, 0/*flags*/));

    return 0;
};

__global__ void
memsetIntKernel(/*hipLaunchParm lp,*/ int * ptr, const int val, size_t numElements)
{
    int gid = (hipBlockIdx_x * hipBlockDim_x + hipThreadIdx_x);
    int stride = hipBlockDim_x * hipGridDim_x ;
    for (size_t i= gid; i< numElements; i+=stride){
       ptr[i] = val;
    }
};

__global__ void
memcpyIntKernel(/*hipLaunchParm lp, */const int * src, int* dst, size_t numElements)
{
    int gid = (hipBlockIdx_x * hipBlockDim_x + hipThreadIdx_x);
    int stride = hipBlockDim_x * hipGridDim_x ;
    for (size_t i= gid; i< numElements; i+=stride){
       dst[i] = src[i];
    }
};

void checkReverse(const int *ptr, int numElements, int expected) {
    for (int i=numElements-1; i>=0; i--) {
        if (ptr[i] != expected) {
            printf ("i=%d, ptr[](%d) != expected (%d)\n", i, ptr[i], expected);
            assert (ptr[i] == expected);
        }
    }

    printf ("test:   OK\n");
}

void runTest(bool stepAIsCopy, bool hostSync, hipStream_t gpu0Stream, hipStream_t gpu1Stream, int numElements,
             int * dataGpu0_0, int * dataGpu0_1, int *dataGpu1, int *dataHost, int expected)
{
    hipEvent_t e;
    if(!hostSync) {
        HIPCHECK(hipEventCreateWithFlags(&e,0));
    }
    const size_t sizeElements = numElements * sizeof(int);
    printf ("test: runTest with %zu bytes %s with hostSync %s\n", sizeElements, stepAIsCopy ? "copy" : "kernel", hostSync ? "enabled" : "disabled");

    hipStream_t stepAStream = gpu0Stream;

    if (stepAIsCopy) {
        HIPCHECK(hipMemcpyAsync(dataGpu1, dataGpu0_0, sizeElements, hipMemcpyDeviceToDevice, stepAStream));
    } else {
        unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, numElements);
        hipLaunchKernelGGL(memcpyIntKernel, dim3(blocks), dim3(threadsPerBlock), 0, gpu0Stream,
                       dataGpu0_0, dataGpu1, numElements);
    }

    if(!hostSync) {
        HIPCHECK(hipEventRecord(e, stepAStream));
        HIPCHECK(hipStreamWaitEvent(gpu1Stream, e, 0));
    } else {
        HIPCHECK(hipStreamSynchronize(stepAStream));
    }

    HIPCHECK(hipMemcpyAsync(dataGpu0_1, dataGpu1, sizeElements, hipMemcpyDeviceToDevice, gpu1Stream));

    if(!hostSync) {
        HIPCHECK(hipEventRecord(e, gpu1Stream));
    } else {
        HIPCHECK(hipStreamSynchronize(gpu1Stream));
    }

    HIPCHECK(hipMemcpyAsync(dataHost, dataGpu0_1, sizeElements, hipMemcpyDeviceToHost, gpu0Stream));
    HIPCHECK(hipStreamSynchronize(gpu0Stream));

    checkReverse(dataHost, numElements, expected);
}

void testMultiGpu(int dev0, int dev1, int numElements, bool hostSync, bool useMemcpy)
{
    const size_t sizeElements = numElements * sizeof(int);

    int * dataGpu0_0, * dataGpu0_1, *dataGpu1, *dataHost;
    hipStream_t gpu0Stream, gpu1Stream;
    const int expected = 42;
    unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, numElements);

    HIPCHECK(hipSetDevice(dev0));

    HIPCHECK(hipMalloc(&dataGpu0_0, sizeElements));
    HIPCHECK(hipMalloc(&dataGpu0_1, sizeElements));
    HIPCHECK(hipStreamCreate(&gpu0Stream));
    hipLaunchKernelGGL(memsetIntKernel, dim3(blocks), dim3(threadsPerBlock), 0, gpu0Stream,
                       dataGpu0_0, expected, numElements);
    HIPCHECK(hipDeviceSynchronize());

    HIPCHECK(hipSetDevice(dev1));
    HIPCHECK(hipMalloc(&dataGpu1, sizeElements));
    HIPCHECK(hipStreamCreate(&gpu1Stream));
    hipLaunchKernelGGL(memsetIntKernel, dim3(blocks), dim3(threadsPerBlock), 0, gpu0Stream,
                       dataGpu1, 0x34, numElements);
    HIPCHECK(hipDeviceSynchronize());

    HIPCHECK(hipHostMalloc(&dataHost, sizeElements));
    memset(dataHost, 13, sizeElements);

#if USE_HCC_MEMTRACKER
    hc::am_memtracker_print(0x0);
#endif

    printf ("  test: init complete\n");
    runTest(useMemcpy , hostSync, gpu0Stream, gpu1Stream, numElements, dataGpu0_0,dataGpu0_1, dataGpu1, dataHost, expected);

    HIPCHECK(hipFree(dataGpu0_0));
    HIPCHECK(hipFree(dataGpu0_1));
    HIPCHECK(hipFree(dataGpu1));
    HIPCHECK(hipHostFree(dataHost));
};

int main(int argc, char *argv[])
{
    HipTest::parseStandardArguments(argc, argv, true);

    int numElements = N;

    int dev0 = 0;
    int dev1 = 1;

    int numDevices;
    HIPCHECK(hipGetDeviceCount(&numDevices));
    if (numDevices == 1) {
        printf("warning : test requires atleast two gpus\n");
        passed();
    }

    if (enablePeers(dev0,dev1) == -1) {
        printf ("warning : could not find peer gpus\n");
        return -1;
    };

    for(int index = 1;index < nSizes;index++) {
        testMultiGpu(dev0, dev1, elementSizes[index] , false /* GPU Synchronization*/, true);
        testMultiGpu(dev0, dev1, elementSizes[index] , true /*Host Synchronization*/, true);
        testMultiGpu(dev0, dev1, elementSizes[index] , true /*Host Synchronization*/, false);
        testMultiGpu(dev0, dev1, elementSizes[index] , false /*Host Synchronization*/, false);
    }

    passed();
};
<commit_msg>Disable failing test p2p_copy_coherency<commit_after>/*
Copyright (c) 2015-2017 Advanced Micro Devices, Inc. All rights reserved.

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

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

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

/* HIT_START
 * BUILD: %t %s ../../test_common.cpp NVCC_OPTIONS --std=c++11
 * RUN: %t EXCLUDE_HIP_PLATFORM all
 * HIT_END
 */

#include "hip/hip_runtime.h"
#include "test_common.h"

#ifdef __HIP_PLATFORM_HCC__
#include <hc_am.hpp>
#define USE_HCC_MEMTRACKER 0
#endif

int elementSizes[] = {16, 1024,524288};
int nSizes  = sizeof(elementSizes) / sizeof(int);

int enablePeers(int dev0, int dev1)
{
    int canAccessPeer01, canAccessPeer10;
    HIPCHECK(hipDeviceCanAccessPeer(&canAccessPeer01, dev0, dev1));
    HIPCHECK(hipDeviceCanAccessPeer(&canAccessPeer10, dev1, dev0));
    if (!canAccessPeer01 || !canAccessPeer10) {
        return -1;
    }

    HIPCHECK(hipSetDevice(dev0));
    HIPCHECK(hipDeviceEnablePeerAccess(dev1, 0/*flags*/));
    HIPCHECK(hipSetDevice(dev1));
    HIPCHECK(hipDeviceEnablePeerAccess(dev0, 0/*flags*/));

    return 0;
};

__global__ void
memsetIntKernel(/*hipLaunchParm lp,*/ int * ptr, const int val, size_t numElements)
{
    int gid = (hipBlockIdx_x * hipBlockDim_x + hipThreadIdx_x);
    int stride = hipBlockDim_x * hipGridDim_x ;
    for (size_t i= gid; i< numElements; i+=stride){
       ptr[i] = val;
    }
};

__global__ void
memcpyIntKernel(/*hipLaunchParm lp, */const int * src, int* dst, size_t numElements)
{
    int gid = (hipBlockIdx_x * hipBlockDim_x + hipThreadIdx_x);
    int stride = hipBlockDim_x * hipGridDim_x ;
    for (size_t i= gid; i< numElements; i+=stride){
       dst[i] = src[i];
    }
};

void checkReverse(const int *ptr, int numElements, int expected) {
    for (int i=numElements-1; i>=0; i--) {
        if (ptr[i] != expected) {
            printf ("i=%d, ptr[](%d) != expected (%d)\n", i, ptr[i], expected);
            assert (ptr[i] == expected);
        }
    }

    printf ("test:   OK\n");
}

void runTest(bool stepAIsCopy, bool hostSync, hipStream_t gpu0Stream, hipStream_t gpu1Stream, int numElements,
             int * dataGpu0_0, int * dataGpu0_1, int *dataGpu1, int *dataHost, int expected)
{
    hipEvent_t e;
    if(!hostSync) {
        HIPCHECK(hipEventCreateWithFlags(&e,0));
    }
    const size_t sizeElements = numElements * sizeof(int);
    printf ("test: runTest with %zu bytes %s with hostSync %s\n", sizeElements, stepAIsCopy ? "copy" : "kernel", hostSync ? "enabled" : "disabled");

    hipStream_t stepAStream = gpu0Stream;

    if (stepAIsCopy) {
        HIPCHECK(hipMemcpyAsync(dataGpu1, dataGpu0_0, sizeElements, hipMemcpyDeviceToDevice, stepAStream));
    } else {
        unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, numElements);
        hipLaunchKernelGGL(memcpyIntKernel, dim3(blocks), dim3(threadsPerBlock), 0, gpu0Stream,
                       dataGpu0_0, dataGpu1, numElements);
    }

    if(!hostSync) {
        HIPCHECK(hipEventRecord(e, stepAStream));
        HIPCHECK(hipStreamWaitEvent(gpu1Stream, e, 0));
    } else {
        HIPCHECK(hipStreamSynchronize(stepAStream));
    }

    HIPCHECK(hipMemcpyAsync(dataGpu0_1, dataGpu1, sizeElements, hipMemcpyDeviceToDevice, gpu1Stream));

    if(!hostSync) {
        HIPCHECK(hipEventRecord(e, gpu1Stream));
    } else {
        HIPCHECK(hipStreamSynchronize(gpu1Stream));
    }

    HIPCHECK(hipMemcpyAsync(dataHost, dataGpu0_1, sizeElements, hipMemcpyDeviceToHost, gpu0Stream));
    HIPCHECK(hipStreamSynchronize(gpu0Stream));

    checkReverse(dataHost, numElements, expected);
}

void testMultiGpu(int dev0, int dev1, int numElements, bool hostSync, bool useMemcpy)
{
    const size_t sizeElements = numElements * sizeof(int);

    int * dataGpu0_0, * dataGpu0_1, *dataGpu1, *dataHost;
    hipStream_t gpu0Stream, gpu1Stream;
    const int expected = 42;
    unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, numElements);

    HIPCHECK(hipSetDevice(dev0));

    HIPCHECK(hipMalloc(&dataGpu0_0, sizeElements));
    HIPCHECK(hipMalloc(&dataGpu0_1, sizeElements));
    HIPCHECK(hipStreamCreate(&gpu0Stream));
    hipLaunchKernelGGL(memsetIntKernel, dim3(blocks), dim3(threadsPerBlock), 0, gpu0Stream,
                       dataGpu0_0, expected, numElements);
    HIPCHECK(hipDeviceSynchronize());

    HIPCHECK(hipSetDevice(dev1));
    HIPCHECK(hipMalloc(&dataGpu1, sizeElements));
    HIPCHECK(hipStreamCreate(&gpu1Stream));
    hipLaunchKernelGGL(memsetIntKernel, dim3(blocks), dim3(threadsPerBlock), 0, gpu0Stream,
                       dataGpu1, 0x34, numElements);
    HIPCHECK(hipDeviceSynchronize());

    HIPCHECK(hipHostMalloc(&dataHost, sizeElements));
    memset(dataHost, 13, sizeElements);

#if USE_HCC_MEMTRACKER
    hc::am_memtracker_print(0x0);
#endif

    printf ("  test: init complete\n");
    runTest(useMemcpy , hostSync, gpu0Stream, gpu1Stream, numElements, dataGpu0_0,dataGpu0_1, dataGpu1, dataHost, expected);

    HIPCHECK(hipFree(dataGpu0_0));
    HIPCHECK(hipFree(dataGpu0_1));
    HIPCHECK(hipFree(dataGpu1));
    HIPCHECK(hipHostFree(dataHost));
};

int main(int argc, char *argv[])
{
    HipTest::parseStandardArguments(argc, argv, true);

    int numElements = N;

    int dev0 = 0;
    int dev1 = 1;

    int numDevices;
    HIPCHECK(hipGetDeviceCount(&numDevices));
    if (numDevices == 1) {
        printf("warning : test requires atleast two gpus\n");
        passed();
    }

    if (enablePeers(dev0,dev1) == -1) {
        printf ("warning : could not find peer gpus\n");
        return -1;
    };

    for(int index = 1;index < nSizes;index++) {
        testMultiGpu(dev0, dev1, elementSizes[index] , false /* GPU Synchronization*/, true);
        testMultiGpu(dev0, dev1, elementSizes[index] , true /*Host Synchronization*/, true);
        testMultiGpu(dev0, dev1, elementSizes[index] , true /*Host Synchronization*/, false);
        testMultiGpu(dev0, dev1, elementSizes[index] , false /*Host Synchronization*/, false);
    }

    passed();
};
<|endoftext|>


<commit_before>#ifdef WIN32
	#include <intrin.h>
	#include <windows.h>
#endif
#include "glresource.hpp"
#include "event.hpp"

namespace rs {
	namespace {
		bool g_bglfuncInit = false;
	}
	#define GLGETPROC(name) SDL_GL_GetProcAddress(#name)
	#if defined(_WIN32)
		namespace {
			using SetSwapInterval_t = bool APIENTRY (*)(int);
			SetSwapInterval_t g_setswapinterval = nullptr;
		}
		void LoadGLAux() {
			g_setswapinterval = (SetSwapInterval_t)wglGetProcAddress("wglSwapIntervalEXT");
		}
	#else
		namespace {
			using SetSwapInterval_t = void APIENTRY (*)(int);
			SetSwapInterval_t g_setswapinterval = nullptr;
		}
		void LoadGLAux() {
			// EXTかSGIのどちらかが存在する事を期待
			try {
				g_setswapinterval = (SetSwapInterval_t)GLGETPROC(glXSwapIntervalSGI);
			} catch(const std::runtime_error& e) {
				g_setswapinterval = (SetSwapInterval_t)GLGETPROC(glXSwapIntervalEXT);
			}
		}
	#endif
	bool GLWrap::isGLFuncLoaded() {
		return g_bglfuncInit;
	}
	void IGL_Draw::setSwapInterval(int n) {
		g_setswapinterval(n);
	}
	void IGL_OtherSingle::setSwapInterval(int n) {
		GLW.getDrawHandler().postExec([=](){
			IGL_Draw().setSwapInterval(n);
		});
	}

	// OpenGL関数ロード
	#define GLDEFINE(...)
 	#define DEF_GLMETHOD(ret_type, name, args, argnames) \
		GLWrap::name = nullptr; \
 		GLWrap::name = (typename GLWrap::t_##name) GLGETPROC(name); \
		Assert(Warn, GLWrap::name != nullptr, "could not load OpenGL function: %1%", #name)
		void GLWrap::loadGLFunc() {
			// 各種API関数
			#ifndef ANDROID
				#ifdef ANDROID
					#include "android_gl.inc"
				#elif defined(WIN32)
					#include "mingw_gl.inc"
				#else
					#include "linux_gl.inc"
				#endif
			#endif
			// その他OS依存なAPI関数
			LoadGLAux();
			g_bglfuncInit = true;
		}
	#undef DEF_GLMETHOD
	#undef GLDEFINE
	// ---------------------- GLShader ----------------------
	void GLShader::_initShader() {
		_idSh = GL.glCreateShader(_flag);

		std::string ss("#version 110\n");
		ss.append(_source);
		const auto* pStr = ss.c_str();
		GL.glShaderSource(_idSh, 1, &pStr, nullptr);
		GL.glCompileShader(_idSh);

		// エラーが無かったか確認
		GLint compiled;
		GL.glGetShaderiv(_idSh, GL_COMPILE_STATUS, &compiled);
		AssertT(Trap, compiled==GL_TRUE, (GLE_ShaderError)(const std::string&)(GLuint), ss, _idSh)
	}

	GLShader::GLShader() {}
	GLShader::GLShader(GLuint flag, const std::string& src): _flag(flag), _source(src) {
		_initShader();
	}
	GLShader::~GLShader() {
		onDeviceLost();
	}
	bool GLShader::isEmpty() const {
		return _source.empty();
	}
	int GLShader::getShaderID() const {
		return _idSh;
	}
	void GLShader::onDeviceLost() {
		if(_idSh!=0) {
			GL.glDeleteShader(_idSh);
			_idSh = 0;
		}
	}
	void GLShader::onDeviceReset() {
		if(!isEmpty() && _idSh==0)
			_initShader();
	}

	// ---------------------- draw::Program ----------------------
	namespace draw {
		Program::Program(HProg hProg):
			Token(hProg), _idProg(hProg.ref()->getProgramID()) {}
		Program::Program(Program&& p): Token(p), _idProg(p._idProg) {}
		void Program::exec() {
			GL.glUseProgram(_idProg);
		}
	}

	// ---------------------- GLProgram ----------------------
	GLProgram::GLProgram(HSh vsh, HSh psh) {
		_shader[ShType::VERTEX] = vsh;
		_shader[ShType::PIXEL] = psh;
		_initProgram();
	}
	GLProgram::GLProgram(HSh vsh, HSh gsh, HSh psh) {
		_shader[ShType::VERTEX] = vsh;
		_shader[ShType::PIXEL] = psh;
		_shader[ShType::GEOMETRY] = gsh;
		_initProgram();
	}
	void GLProgram::_initProgram() {
		_idProg = GL.glCreateProgram();
		for(int i=0 ; i<static_cast<int>(ShType::NUM_SHTYPE) ; i++) {
			auto& sh = _shader[i];
			// Geometryシェーダー以外は必須
			if(sh.valid()) {
				GL.glAttachShader(_idProg, sh.cref()->getShaderID());
				GLEC_ChkP(Trap)
			} else {
				AssertT(Trap, i==ShType::GEOMETRY, (GLE_Error)(const char*), "missing shader elements (vertex or fragment)")
			}
		}

		GL.glLinkProgram(_idProg);
		// エラーが無いかチェック
		int ib;
		GL.glGetProgramiv(_idProg, GL_LINK_STATUS, &ib);
		AssertT(Trap, ib==GL_TRUE, (GLE_ProgramError)(GLuint), _idProg)
	}
	GLProgram::~GLProgram() {
		if(mgr_gl.isInDtor()) {
			for(auto& p : _shader)
				p.setNull();
		}
		onDeviceLost();
	}
	void GLProgram::onDeviceLost() {
		if(_idProg != 0) {
			// ShaderはProgramをDeleteすれば自動的にdetachされる
			GL.glDeleteProgram(_idProg);
			_idProg = 0;
		}
	}
	void GLProgram::onDeviceReset() {
		if(_idProg == 0) {
			// 先にshaderがresetされてないかもしれないので、ここでしておく
			for(auto& s : _shader) {
				if(s)
					s.cref()->onDeviceReset();
			}
			_initProgram();
		}
	}
	const HLSh& GLProgram::getShader(ShType type) const {
		return _shader[(int)type];
	}
	int GLProgram::getUniformID(const std::string& name) const {
		GLint id = getUniformIDNc(name);
		AssertT(Trap, id>=0, (GLE_ParamNotFound)(const std::string&), name)
		return id;
	}
	int GLProgram::getUniformIDNc(const std::string& name) const {
		return GL.glGetUniformLocation(getProgramID(), name.c_str());
	}
	int GLProgram::getAttribID(const std::string& name) const {
		GLint id = getAttribIDNc(name);
		AssertT(Trap, id>=0, (GLE_ParamNotFound)(const std::string&), name)
		return id;
	}
	GLuint GLProgram::getProgramID() const {
		return _idProg;
	}
	int GLProgram::getAttribIDNc(const std::string& name) const {
		return GL.glGetAttribLocation(getProgramID(), name.c_str());
	}
	void GLProgram::use() const {
		GL.glUseProgram(getProgramID());
		GLEC_ChkP(Trap)
	}
}
<commit_msg>wglSwapIntervalのアドレス読み込みをwglGetProcAddressからSDLの物に変更<commit_after>#ifdef WIN32
	#include <intrin.h>
	#include <windows.h>
#endif
#include "glresource.hpp"
#include "event.hpp"

namespace rs {
	namespace {
		bool g_bglfuncInit = false;
	}
	#define GLGETPROC(name) SDL_GL_GetProcAddress(#name)
	#if defined(_WIN32)
		namespace {
			using SetSwapInterval_t = bool APIENTRY (*)(int);
			SetSwapInterval_t g_setswapinterval = nullptr;
		}
		void LoadGLAux() {
			g_setswapinterval = (SetSwapInterval_t)GLGETPROC(wglSwapIntervalEXT);
		}
	#else
		namespace {
			using SetSwapInterval_t = void APIENTRY (*)(int);
			SetSwapInterval_t g_setswapinterval = nullptr;
		}
		void LoadGLAux() {
			// EXTかSGIのどちらかが存在する事を期待
			try {
				g_setswapinterval = (SetSwapInterval_t)GLGETPROC(glXSwapIntervalSGI);
			} catch(const std::runtime_error& e) {
				g_setswapinterval = (SetSwapInterval_t)GLGETPROC(glXSwapIntervalEXT);
			}
		}
	#endif
	bool GLWrap::isGLFuncLoaded() {
		return g_bglfuncInit;
	}
	void IGL_Draw::setSwapInterval(int n) {
		g_setswapinterval(n);
	}
	void IGL_OtherSingle::setSwapInterval(int n) {
		GLW.getDrawHandler().postExec([=](){
			IGL_Draw().setSwapInterval(n);
		});
	}

	// OpenGL関数ロード
	#define GLDEFINE(...)
 	#define DEF_GLMETHOD(ret_type, name, args, argnames) \
		GLWrap::name = nullptr; \
 		GLWrap::name = (typename GLWrap::t_##name) GLGETPROC(name); \
		Assert(Warn, GLWrap::name != nullptr, "could not load OpenGL function: %1%", #name)
		void GLWrap::loadGLFunc() {
			// 各種API関数
			#ifndef ANDROID
				#ifdef ANDROID
					#include "android_gl.inc"
				#elif defined(WIN32)
					#include "mingw_gl.inc"
				#else
					#include "linux_gl.inc"
				#endif
			#endif
			// その他OS依存なAPI関数
			LoadGLAux();
			g_bglfuncInit = true;
		}
	#undef DEF_GLMETHOD
	#undef GLDEFINE
	// ---------------------- GLShader ----------------------
	void GLShader::_initShader() {
		_idSh = GL.glCreateShader(_flag);

		std::string ss("#version 110\n");
		ss.append(_source);
		const auto* pStr = ss.c_str();
		GL.glShaderSource(_idSh, 1, &pStr, nullptr);
		GL.glCompileShader(_idSh);

		// エラーが無かったか確認
		GLint compiled;
		GL.glGetShaderiv(_idSh, GL_COMPILE_STATUS, &compiled);
		AssertT(Trap, compiled==GL_TRUE, (GLE_ShaderError)(const std::string&)(GLuint), ss, _idSh)
	}

	GLShader::GLShader() {}
	GLShader::GLShader(GLuint flag, const std::string& src): _flag(flag), _source(src) {
		_initShader();
	}
	GLShader::~GLShader() {
		onDeviceLost();
	}
	bool GLShader::isEmpty() const {
		return _source.empty();
	}
	int GLShader::getShaderID() const {
		return _idSh;
	}
	void GLShader::onDeviceLost() {
		if(_idSh!=0) {
			GL.glDeleteShader(_idSh);
			_idSh = 0;
		}
	}
	void GLShader::onDeviceReset() {
		if(!isEmpty() && _idSh==0)
			_initShader();
	}

	// ---------------------- draw::Program ----------------------
	namespace draw {
		Program::Program(HProg hProg):
			Token(hProg), _idProg(hProg.ref()->getProgramID()) {}
		Program::Program(Program&& p): Token(p), _idProg(p._idProg) {}
		void Program::exec() {
			GL.glUseProgram(_idProg);
		}
	}

	// ---------------------- GLProgram ----------------------
	GLProgram::GLProgram(HSh vsh, HSh psh) {
		_shader[ShType::VERTEX] = vsh;
		_shader[ShType::PIXEL] = psh;
		_initProgram();
	}
	GLProgram::GLProgram(HSh vsh, HSh gsh, HSh psh) {
		_shader[ShType::VERTEX] = vsh;
		_shader[ShType::PIXEL] = psh;
		_shader[ShType::GEOMETRY] = gsh;
		_initProgram();
	}
	void GLProgram::_initProgram() {
		_idProg = GL.glCreateProgram();
		for(int i=0 ; i<static_cast<int>(ShType::NUM_SHTYPE) ; i++) {
			auto& sh = _shader[i];
			// Geometryシェーダー以外は必須
			if(sh.valid()) {
				GL.glAttachShader(_idProg, sh.cref()->getShaderID());
				GLEC_ChkP(Trap)
			} else {
				AssertT(Trap, i==ShType::GEOMETRY, (GLE_Error)(const char*), "missing shader elements (vertex or fragment)")
			}
		}

		GL.glLinkProgram(_idProg);
		// エラーが無いかチェック
		int ib;
		GL.glGetProgramiv(_idProg, GL_LINK_STATUS, &ib);
		AssertT(Trap, ib==GL_TRUE, (GLE_ProgramError)(GLuint), _idProg)
	}
	GLProgram::~GLProgram() {
		if(mgr_gl.isInDtor()) {
			for(auto& p : _shader)
				p.setNull();
		}
		onDeviceLost();
	}
	void GLProgram::onDeviceLost() {
		if(_idProg != 0) {
			// ShaderはProgramをDeleteすれば自動的にdetachされる
			GL.glDeleteProgram(_idProg);
			_idProg = 0;
		}
	}
	void GLProgram::onDeviceReset() {
		if(_idProg == 0) {
			// 先にshaderがresetされてないかもしれないので、ここでしておく
			for(auto& s : _shader) {
				if(s)
					s.cref()->onDeviceReset();
			}
			_initProgram();
		}
	}
	const HLSh& GLProgram::getShader(ShType type) const {
		return _shader[(int)type];
	}
	int GLProgram::getUniformID(const std::string& name) const {
		GLint id = getUniformIDNc(name);
		AssertT(Trap, id>=0, (GLE_ParamNotFound)(const std::string&), name)
		return id;
	}
	int GLProgram::getUniformIDNc(const std::string& name) const {
		return GL.glGetUniformLocation(getProgramID(), name.c_str());
	}
	int GLProgram::getAttribID(const std::string& name) const {
		GLint id = getAttribIDNc(name);
		AssertT(Trap, id>=0, (GLE_ParamNotFound)(const std::string&), name)
		return id;
	}
	GLuint GLProgram::getProgramID() const {
		return _idProg;
	}
	int GLProgram::getAttribIDNc(const std::string& name) const {
		return GL.glGetAttribLocation(getProgramID(), name.c_str());
	}
	void GLProgram::use() const {
		GL.glUseProgram(getProgramID());
		GLEC_ChkP(Trap)
	}
}
<|endoftext|>


<commit_before>/*
 *  LSSLRTAStar.cpp
 *  hog2
 *
 *  Created by Nathan Sturtevant on 10/6/09.
 *  Copyright 2009 NS Software. All rights reserved.
 *
 */

#include "LSSLRTAStar.h"

<commit_msg>unneeded file<commit_after><|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN
#include "catch.hpp"

#include <mmtf.hpp>

// Tests for structure_data.hpp
TEST_CASE("Test for equality of StructureData") {
	mmtf::StructureData sd1, sd2;
	REQUIRE( sd1 == sd2 );
}
<commit_msg>not sure how to emulate bytestring<commit_after>#define CATCH_CONFIG_MAIN
#include "catch.hpp"

#include <mmtf.hpp>

// Tests for structure_data.hpp
TEST_CASE("Test for equality of StructureData") {
	mmtf::StructureData sd1, sd2;
	REQUIRE( sd1 == sd2 );
}

TEST_CASE("Test DeltaRecursiveFloat enc/dec") {
	//const char* encoded_data = '\x7f\xffD\xab\x01\x8f\xff\xca';
	char encoded_data[] = "\x7f\xffD\xab\x01\x8f\xff\xca";
	//const char* encoded_data = u"\x007f\x0ffD\x00ab\x0001\x008f\x00ff\x00ca";
	//const char* encoded_data = "\u7f\uffD\uab\u01\u8f\uff\uca";
	//const char* encoded_data = "0x7f0xffD0xab0x010x8f0xff0xca";
	std::vector<float> decoded_data;
	decoded_data.push_back(50.346);
	decoded_data.push_back(50.745);
	decoded_data.push_back(50.691);
	std::cout << "encoded: " << std::string(encoded_data) << std::endl;
//std::cout << "decoded: " << mmtf::encodeDeltaRecursiveFloat(decoded_data, 1000) << std::endl;
	std::vector<char> encode_output = mmtf::encodeDeltaRecursiveFloat(decoded_data, 1000);
	std::string encode_output_str(encode_output.begin(),encode_output.end());
	std::cout << "encoded: " << encode_output_str << std::endl;
	REQUIRE(std::string(encoded_data) == encode_output_str);
}
<|endoftext|>


<commit_before>#ifndef BFC_CLEAR_LOOPS_VISITOR_HPP
#define BFC_CLEAR_LOOPS_VISITOR_HPP

#include "ast/mod.hpp"
#include "test_visitor.hpp"
#include "opt_seq_base_visitor.hpp"

namespace bfc {
namespace ast {

class clear_loops_visitor : public opt_seq_base_visitor {

public:

    status visit(loop &node) {
        if (node.size() == 1) {
            // test if the inner node matches a clear loop
            test_inner_sequence_visitor v;
            if (node.seq::accept(v) == CONTINUE) {
                // replace loop, just set cell to 0
                opt_seq.emplace_back(new set(node.loc(), 0 0));
                return CONTINUE;
            }
        }
        // else optimize inner sequence
        opt_seq_base_visitor::handle_loop(node);
    }

    status visit(const loop &node) {
        if (node.size() == 1) {
            // test if the inner node matches a clear loop
            test_inner_sequence_visitor v;
            if (node.seq::accept(v) == CONTINUE) {
                // replace loop, just set cell to 0
                opt_seq.emplace_back(new set(node.loc(), 0 0));
                return CONTINUE;
            }
        }
        // else optimize inner sequence
        opt_seq_base_visitor::handle_loop(node);
    }

private:

    class test_inner_sequence_visitor : public test_visitor {

        public:
            status visit(add &node) {
                return (node.value() == 1 && node.offset() == 0) ? CONTINUE : BREAK;
            }
            status visit(const add &node) {
                return (node.value() == 1 && node.offset() == 0) ? CONTINUE : BREAK;
            }
            status visit(sub &node) {
                return (node.value() == 1 && node.offset() == 0) ? CONTINUE : BREAK;
            }
            status visit(const sub &node) {
                return (node.value() == 1 && node.offset() == 0) ? CONTINUE : BREAK;
            }

    };

};

}
}

#endif /* !BFC_CLEAR_LOOPS_VISITOR_HPP */
<commit_msg>fix commas missing<commit_after>#ifndef BFC_CLEAR_LOOPS_VISITOR_HPP
#define BFC_CLEAR_LOOPS_VISITOR_HPP

#include "ast/mod.hpp"
#include "test_visitor.hpp"
#include "opt_seq_base_visitor.hpp"

namespace bfc {
namespace ast {

class clear_loops_visitor : public opt_seq_base_visitor {

public:

    status visit(loop &node) {
        if (node.size() == 1) {
            // test if the inner node matches a clear loop
            test_inner_sequence_visitor v;
            if (node.seq::accept(v) == CONTINUE) {
                // replace loop, just set cell to 0
                opt_seq.emplace_back(new set(node.loc(), 0, 0));
                return CONTINUE;
            }
        }
        // else optimize inner sequence
        opt_seq_base_visitor::handle_loop(node);
    }

    status visit(const loop &node) {
        if (node.size() == 1) {
            // test if the inner node matches a clear loop
            test_inner_sequence_visitor v;
            if (node.seq::accept(v) == CONTINUE) {
                // replace loop, just set cell to 0
                opt_seq.emplace_back(new set(node.loc(), 0, 0));
                return CONTINUE;
            }
        }
        // else optimize inner sequence
        opt_seq_base_visitor::handle_loop(node);
    }

private:

    class test_inner_sequence_visitor : public test_visitor {

        public:
            status visit(add &node) {
                return (node.value() == 1 && node.offset() == 0) ? CONTINUE : BREAK;
            }
            status visit(const add &node) {
                return (node.value() == 1 && node.offset() == 0) ? CONTINUE : BREAK;
            }
            status visit(sub &node) {
                return (node.value() == 1 && node.offset() == 0) ? CONTINUE : BREAK;
            }
            status visit(const sub &node) {
                return (node.value() == 1 && node.offset() == 0) ? CONTINUE : BREAK;
            }

    };

};

}
}

#endif /* !BFC_CLEAR_LOOPS_VISITOR_HPP */
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                        OpenSim:  OpenSimContext.cpp                        *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2017 Stanford University and the Authors                *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */
#include <OpenSim/Common/Function.h>
#include <OpenSim/Common/MarkerData.h>
#include <OpenSim/Simulation/SimbodyEngine/Body.h>
#include <OpenSim/Simulation/SimbodyEngine/Coordinate.h>
#include <OpenSim/Simulation/SimbodyEngine/TransformAxis.h>
#include <OpenSim/Simulation/Model/Marker.h>
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Simulation/Model/MovingPathPoint.h>
#include <OpenSim/Simulation/Model/Muscle.h>
#include <OpenSim/Simulation/Model/PathPoint.h>
#include <OpenSim/Simulation/Wrap/PathWrap.h>
#include <OpenSim/Simulation/Model/ConditionalPathPoint.h>
#include <OpenSim/Simulation/SimbodyEngine/SimbodyEngine.h>
#include <OpenSim/Simulation/SimbodyEngine/TransformAxis.h>
#include <OpenSim/Simulation/Wrap/WrapObject.h>
#include <OpenSim/Simulation/Model/Analysis.h>
#include <OpenSim/Simulation/Model/MarkerSet.h>
#include <OpenSim/Tools/InverseKinematicsTool.h>
#include <OpenSim/Tools/AnalyzeTool.h>
#include <OpenSim/Tools/ModelScaler.h>
#include <OpenSim/Tools/Measurement.h>
#include <OpenSim/Tools/MarkerPlacer.h>
#include <OpenSim/Simulation/Model/ForceSet.h>
#include "OpenSimContext.h"

namespace OpenSim {

OpenSimContext::OpenSimContext( SimTK::State* s, Model* model ) :
    _configState(s),
  _model(model) {}

// Transforms
void OpenSimContext::transformPosition(const PhysicalFrame& body, double* offset, double* gOffset) {
    _model->getMultibodySystem().realize(*_configState, SimTK::Stage::Position);
    SimTK::Vec3::updAs(gOffset) =
        body.findStationLocationInGround(*_configState, SimTK::Vec3(offset));
}

SimTK::Transform OpenSimContext::getTransform(const PhysicalFrame& body) { // Body Should be made const
     _model->getMultibodySystem().realize(*_configState, SimTK::Stage::Position);
     return body.getTransformInGround(*_configState);
}

void OpenSimContext::transform(const PhysicalFrame& ground, double* d, PhysicalFrame& body, double* dragVectorBody) {
    _model->getMultibodySystem().realize(*_configState, SimTK::Stage::Position);
    SimTK::Vec3::updAs(dragVectorBody) =
        ground.expressVectorInAnotherFrame(*_configState, SimTK::Vec3(d), body);
    return;
}

// Coordinates
double OpenSimContext::getValue(const Coordinate& coord) {
        return( coord.getValue( *_configState));
}

bool OpenSimContext::getLocked(const Coordinate& coord) {
    return coord.getLocked(*_configState);
}
void OpenSimContext::setValue(const Coordinate& coord, double d, bool enforceConstraints) {
  coord.setValue(*_configState, d, enforceConstraints);
    return;
}

void OpenSimContext::setClamped(Coordinate&  coord, bool newValue) {
   coord.setDefaultClamped(newValue);
   recreateSystemKeepStage();
   return;
}

bool OpenSimContext::getClamped(const Coordinate& coord) {
  return coord.getClamped(*_configState);
}

void OpenSimContext::setLocked(Coordinate& coord, bool newValue) {
   coord.setDefaultValue(getValue(coord));
   coord.setDefaultLocked(newValue);
   recreateSystemKeepStage();
   return;
}

bool OpenSimContext::isPrescribed(const Coordinate& coord) const {
  return (coord.isPrescribed(*_configState));
}

bool OpenSimContext::isConstrained(const Coordinate& coord) const {
  return (coord.isDependent(*_configState));
}

// Muscles
double OpenSimContext::getActivation(Muscle& m) {
  // realize to dynamics as required by new muscle models before asking for activation
  _model->getMultibodySystem().realize(*_configState, SimTK::Stage::Dynamics);
  return m.getActivation(*_configState);
}

double OpenSimContext::getMuscleLength(Muscle& m) {
  return m.getLength(*_configState);
}

const Array<AbstractPathPoint*>& OpenSimContext::getCurrentPath(Muscle& m) {
  return m.getGeometryPath().getCurrentPath(*_configState);
}

void OpenSimContext::copyMuscle(Muscle& from, Muscle& to) {
  to = from;
  recreateSystemKeepStage();
  to.updGeometryPath().updateGeometry(*_configState);
}

// Muscle Points
void OpenSimContext::setXFunction(MovingPathPoint& mmp, Function& newFunction) {
    mmp.set_x_location(newFunction );
    recreateSystemKeepStage();
   return;
}

void OpenSimContext::setYFunction(MovingPathPoint& mmp, Function& newFunction) {
    mmp.set_y_location(newFunction );
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::setZFunction(MovingPathPoint& mmp, Function& newFunction) {
    mmp.set_z_location(newFunction );
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::setXCoordinate(MovingPathPoint& mmp, Coordinate&  newCoord) {
    mmp.setXCoordinate(newCoord);
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::setYCoordinate(MovingPathPoint& mmp, Coordinate&  newCoord) {
    mmp.setYCoordinate( newCoord );
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::setZCoordinate(MovingPathPoint& mmp, Coordinate&  newCoord) {
    mmp.setZCoordinate( newCoord );
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::setBody(AbstractPathPoint& pathPoint, PhysicalFrame&  newBody)
{
    PathPoint* spp = dynamic_cast<PathPoint*>(&pathPoint);
    if (spp) {
        spp->changeBodyPreserveLocation(*_configState, newBody);
        this->recreateSystemAfterSystemExists();
        realizeVelocity();
        return;
    }
    MovingPathPoint* mpp = dynamic_cast<MovingPathPoint*>(&pathPoint);
    if (mpp) {
        mpp->setParentFrame(newBody);
        this->recreateSystemAfterSystemExists();
        realizeVelocity();
    }
}

//-------------------------------------------------------------------
void OpenSimContext::recreateSystemAfterSystemExistsKeepStage( )
{
   SimTK::Stage stageBeforeRecreatingSystem = _configState->getSystemStage();
   this->recreateSystemAfterSystemExists();
  _model->getMultibodySystem().realize( *_configState, stageBeforeRecreatingSystem );
}

//-------------------------------------------------------------------
void OpenSimContext::recreateSystemAfterSystemExists( )
{
  SimTK::Vector y1 = _configState->getY();
  SimTK::State* newState = &_model->initSystem();
  newState->updY() = y1;
  this->setState( newState );
}

void OpenSimContext::setCoordinate(ConditionalPathPoint&  via, Coordinate&  newCoord) {
    via.setCoordinate( newCoord );
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::setRangeMin(ConditionalPathPoint&  via, double d) {
     via.setRangeMin( d );
     recreateSystemKeepStage();
     return;
}

void OpenSimContext::setRangeMax(ConditionalPathPoint&  via, double d) {
    via.setRangeMax( d );
    recreateSystemKeepStage();
    return;
}

bool OpenSimContext::replacePathPoint(GeometryPath& p, AbstractPathPoint& mp, AbstractPathPoint& newPoint) {
   bool ret= p.replacePathPoint(*_configState, &mp, &newPoint );
   recreateSystemAfterSystemExists();
   realizeVelocity();
   p.updateGeometry(*_configState);
   return ret;
}

void OpenSimContext::setLocation(PathPoint& mp, int i, double d) {
    SimTK::Vec3 loc = mp.getLocation(*_configState);
    loc[i] = d;
    mp.setLocation(loc);
    recreateSystemKeepStage();
}

void OpenSimContext::setEndPoint(PathWrap& mw, int newEndPt) {
    mw.setEndPoint(*_configState, newEndPt );
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::addPathPoint(GeometryPath& p, int menuChoice, PhysicalFrame&  body) {
    p.addPathPoint(*_configState, menuChoice, body );
    recreateSystemKeepStage();
    p.updateGeometry(*_configState);
    return;
}

bool OpenSimContext::deletePathPoint(GeometryPath& p, int menuChoice) {
    bool ret = p.deletePathPoint(*_configState, menuChoice );
    recreateSystemKeepStage();
    return ret;
}

bool OpenSimContext::isActivePathPoint(AbstractPathPoint& mp) {
  return mp.isActive(*_configState);
};

//_____________________________________________________________________________
/**
 * Replace one of the actuator's functions in the property array.
 *
 * @param aOldFunction the function being replaced.
 * @param aNewFunction the new function.
 */
void OpenSimContext::replacePropertyFunction(OpenSim::Object& obj, OpenSim::Function* aOldFunction, OpenSim::Function* aNewFunction)
{
  if (aOldFunction && aNewFunction) {
    PropertySet& propSet = obj.getPropertySet();

    for (int i=0; i <propSet.getSize(); i++) {
      Property_Deprecated* prop = propSet.get(i);
      if (prop->getType() == Property_Deprecated::ObjPtr) {
        if (prop->getValueObjPtr() == aOldFunction) {
          prop->setValue(aNewFunction);
        }
      }
    }
  }
}

// Muscle Wrapping
void OpenSimContext::setStartPoint(PathWrap& mw, int newStartPt) {
     mw.setStartPoint(*_configState, newStartPt );
     return;
}

void OpenSimContext::addPathWrap(GeometryPath& p, WrapObject& awo) {
    p.addPathWrap( awo );
    return;
}

void OpenSimContext::moveUpPathWrap(GeometryPath& p, int num) {
    p.moveUpPathWrap( *_configState, num );
    recreateSystemKeepStage();
    p.updateGeometry(*_configState);
    return;
}

void OpenSimContext::moveDownPathWrap(GeometryPath& p, int num) {
    p.moveDownPathWrap( *_configState, num );
    recreateSystemKeepStage();
    p.updateGeometry(*_configState);
    return;
}

void OpenSimContext::deletePathWrap(GeometryPath& p, int num) {
    p.deletePathWrap( *_configState, num );
    recreateSystemKeepStage();
    p.updateGeometry(*_configState);
    return;
}

// Markers
void OpenSimContext::setBody(Marker& currentMarker, PhysicalFrame&  newBody, bool b) {
    if( b ) {
         currentMarker.changeFramePreserveLocation( *_configState, newBody );
    } else {
         currentMarker.changeFrame( newBody );
    }
    return;
}

int OpenSimContext::replaceMarkerSet(Model& model, MarkerSet& aMarkerSet) {
  return model.replaceMarkerSet( *_configState, aMarkerSet);
}

// Analyses
int OpenSimContext::step(Analysis& analysis)
{
  return analysis.step( *_configState, 0);
}

// Tools
/*
bool OpenSimContext::initializeTrial(IKTool& ikTool, int i) {
  return ikTool.initializeTrial(*_configState, i);
}
*/
bool OpenSimContext::solveInverseKinematics( InverseKinematicsTool& ikTool) {
  return ikTool.run();
}

void OpenSimContext::setStatesFromMotion(AnalyzeTool& analyzeTool, const Storage &aMotion, bool aInDegrees) {
  analyzeTool.setStatesFromMotion(*_configState, aMotion, aInDegrees);
}

void OpenSimContext::loadStatesFromFile(AnalyzeTool& analyzeTool) {
  analyzeTool.loadStatesFromFile(*_configState);
}

bool OpenSimContext::processModelScale(ModelScaler& modelScaler,
                     Model* aModel,
                     const std::string& aPathToSubject,
                     double aFinalMass) {
  aModel->getMultibodySystem().realizeTopology();
    _configState=&aModel->updWorkingState();
  bool retValue= modelScaler.processModel(aModel, aPathToSubject, aFinalMass);
  // Model has changed need to recreate a valid state
  aModel->getMultibodySystem().realizeTopology();
    _configState=&aModel->updWorkingState();
  aModel->getMultibodySystem().realize(*_configState, SimTK::Stage::Position);
  return retValue;
}

bool OpenSimContext::processModelMarkerPlacer( MarkerPlacer& markerPlacer,
                        Model* aModel,
                        const std::string& aPathToSubject) {
  return markerPlacer.processModel(aModel, aPathToSubject);
}

double OpenSimContext::computeMeasurementScaleFactor(ModelScaler& modelScaler,
                           const Model& aModel,
                           const MarkerData& aMarkerData,
                           const Measurement& aMeasurement) const {
  return modelScaler.computeMeasurementScaleFactor(*_configState, aModel, aMarkerData, aMeasurement);
}

void OpenSimContext::replaceTransformAxisFunction(TransformAxis& aDof, OpenSim::Function& aFunction) {
   aDof.setFunction(&aFunction);
   this->recreateSystemAfterSystemExists();
   realizeVelocity();
}

// Force re-realization
void OpenSimContext::realizePosition() {
  _model->getMultibodySystem().realize(*_configState, SimTK::Stage::Position);

}
void OpenSimContext::realizeVelocity() {
  _model->getMultibodySystem().realize(*_configState, SimTK::Stage::Velocity);

}

void OpenSimContext::cacheModelAndState()
{
    clonedModel = _model->clone();
    clonedState = this->getCurrentStateCopy();
}

void OpenSimContext::restoreStateFromCachedModel()
{
    _model->initSystem();
    clonedModel->initSystem();

    Array<std::string> modelVariableNames = _model->getStateVariableNames();
    Array<std::string> clonedModelVariableNames = clonedModel->getStateVariableNames();

    for(int i = 0; i < modelVariableNames.getSize(); i++)
    {
        std::string name = modelVariableNames.get(i);
        if(clonedModelVariableNames.findIndex(name) >= 0)
        {
            double value = clonedModel->getStateVariableValue(clonedState, name);
            _model->setStateVariableValue(_model->updWorkingState(), name, value);
        }
    }
    this->setState(&(_model->updWorkingState()));
    this->realizePosition();
    delete clonedModel;
}
} // namespace
<commit_msg>No need to recreate system if PathPoint can't be deleted. Address feedback on PR<commit_after>/* -------------------------------------------------------------------------- *
 *                        OpenSim:  OpenSimContext.cpp                        *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2017 Stanford University and the Authors                *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */
#include <OpenSim/Common/Function.h>
#include <OpenSim/Common/MarkerData.h>
#include <OpenSim/Simulation/SimbodyEngine/Body.h>
#include <OpenSim/Simulation/SimbodyEngine/Coordinate.h>
#include <OpenSim/Simulation/SimbodyEngine/TransformAxis.h>
#include <OpenSim/Simulation/Model/Marker.h>
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Simulation/Model/MovingPathPoint.h>
#include <OpenSim/Simulation/Model/Muscle.h>
#include <OpenSim/Simulation/Model/PathPoint.h>
#include <OpenSim/Simulation/Wrap/PathWrap.h>
#include <OpenSim/Simulation/Model/ConditionalPathPoint.h>
#include <OpenSim/Simulation/SimbodyEngine/SimbodyEngine.h>
#include <OpenSim/Simulation/SimbodyEngine/TransformAxis.h>
#include <OpenSim/Simulation/Wrap/WrapObject.h>
#include <OpenSim/Simulation/Model/Analysis.h>
#include <OpenSim/Simulation/Model/MarkerSet.h>
#include <OpenSim/Tools/InverseKinematicsTool.h>
#include <OpenSim/Tools/AnalyzeTool.h>
#include <OpenSim/Tools/ModelScaler.h>
#include <OpenSim/Tools/Measurement.h>
#include <OpenSim/Tools/MarkerPlacer.h>
#include <OpenSim/Simulation/Model/ForceSet.h>
#include "OpenSimContext.h"

namespace OpenSim {

OpenSimContext::OpenSimContext( SimTK::State* s, Model* model ) :
    _configState(s),
  _model(model) {}

// Transforms
void OpenSimContext::transformPosition(const PhysicalFrame& body, double* offset, double* gOffset) {
    _model->getMultibodySystem().realize(*_configState, SimTK::Stage::Position);
    SimTK::Vec3::updAs(gOffset) =
        body.findStationLocationInGround(*_configState, SimTK::Vec3(offset));
}

SimTK::Transform OpenSimContext::getTransform(const PhysicalFrame& body) { // Body Should be made const
     _model->getMultibodySystem().realize(*_configState, SimTK::Stage::Position);
     return body.getTransformInGround(*_configState);
}

void OpenSimContext::transform(const PhysicalFrame& ground, double* d, PhysicalFrame& body, double* dragVectorBody) {
    _model->getMultibodySystem().realize(*_configState, SimTK::Stage::Position);
    SimTK::Vec3::updAs(dragVectorBody) =
        ground.expressVectorInAnotherFrame(*_configState, SimTK::Vec3(d), body);
    return;
}

// Coordinates
double OpenSimContext::getValue(const Coordinate& coord) {
        return( coord.getValue( *_configState));
}

bool OpenSimContext::getLocked(const Coordinate& coord) {
    return coord.getLocked(*_configState);
}
void OpenSimContext::setValue(const Coordinate& coord, double d, bool enforceConstraints) {
  coord.setValue(*_configState, d, enforceConstraints);
    return;
}

void OpenSimContext::setClamped(Coordinate&  coord, bool newValue) {
   coord.setDefaultClamped(newValue);
   recreateSystemKeepStage();
   return;
}

bool OpenSimContext::getClamped(const Coordinate& coord) {
  return coord.getClamped(*_configState);
}

void OpenSimContext::setLocked(Coordinate& coord, bool newValue) {
   coord.setDefaultValue(getValue(coord));
   coord.setDefaultLocked(newValue);
   recreateSystemKeepStage();
   return;
}

bool OpenSimContext::isPrescribed(const Coordinate& coord) const {
  return (coord.isPrescribed(*_configState));
}

bool OpenSimContext::isConstrained(const Coordinate& coord) const {
  return (coord.isDependent(*_configState));
}

// Muscles
double OpenSimContext::getActivation(Muscle& m) {
  // realize to dynamics as required by new muscle models before asking for activation
  _model->getMultibodySystem().realize(*_configState, SimTK::Stage::Dynamics);
  return m.getActivation(*_configState);
}

double OpenSimContext::getMuscleLength(Muscle& m) {
  return m.getLength(*_configState);
}

const Array<AbstractPathPoint*>& OpenSimContext::getCurrentPath(Muscle& m) {
  return m.getGeometryPath().getCurrentPath(*_configState);
}

void OpenSimContext::copyMuscle(Muscle& from, Muscle& to) {
  to = from;
  recreateSystemKeepStage();
  to.updGeometryPath().updateGeometry(*_configState);
}

// Muscle Points
void OpenSimContext::setXFunction(MovingPathPoint& mmp, Function& newFunction) {
    mmp.set_x_location(newFunction );
    recreateSystemKeepStage();
   return;
}

void OpenSimContext::setYFunction(MovingPathPoint& mmp, Function& newFunction) {
    mmp.set_y_location(newFunction );
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::setZFunction(MovingPathPoint& mmp, Function& newFunction) {
    mmp.set_z_location(newFunction );
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::setXCoordinate(MovingPathPoint& mmp, Coordinate&  newCoord) {
    mmp.setXCoordinate(newCoord);
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::setYCoordinate(MovingPathPoint& mmp, Coordinate&  newCoord) {
    mmp.setYCoordinate( newCoord );
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::setZCoordinate(MovingPathPoint& mmp, Coordinate&  newCoord) {
    mmp.setZCoordinate( newCoord );
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::setBody(AbstractPathPoint& pathPoint, PhysicalFrame&  newBody)
{
    PathPoint* spp = dynamic_cast<PathPoint*>(&pathPoint);
    if (spp) {
        spp->changeBodyPreserveLocation(*_configState, newBody);
        this->recreateSystemAfterSystemExists();
        realizeVelocity();
        return;
    }
    MovingPathPoint* mpp = dynamic_cast<MovingPathPoint*>(&pathPoint);
    if (mpp) {
        mpp->setParentFrame(newBody);
        this->recreateSystemAfterSystemExists();
        realizeVelocity();
    }
}

//-------------------------------------------------------------------
void OpenSimContext::recreateSystemAfterSystemExistsKeepStage( )
{
   SimTK::Stage stageBeforeRecreatingSystem = _configState->getSystemStage();
   this->recreateSystemAfterSystemExists();
  _model->getMultibodySystem().realize( *_configState, stageBeforeRecreatingSystem );
}

//-------------------------------------------------------------------
void OpenSimContext::recreateSystemAfterSystemExists( )
{
  SimTK::Vector y1 = _configState->getY();
  SimTK::State* newState = &_model->initSystem();
  newState->updY() = y1;
  this->setState( newState );
}

void OpenSimContext::setCoordinate(ConditionalPathPoint&  via, Coordinate&  newCoord) {
    via.setCoordinate( newCoord );
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::setRangeMin(ConditionalPathPoint&  via, double d) {
     via.setRangeMin( d );
     recreateSystemKeepStage();
     return;
}

void OpenSimContext::setRangeMax(ConditionalPathPoint&  via, double d) {
    via.setRangeMax( d );
    recreateSystemKeepStage();
    return;
}

bool OpenSimContext::replacePathPoint(GeometryPath& p, AbstractPathPoint& mp, AbstractPathPoint& newPoint) {
   bool ret= p.replacePathPoint(*_configState, &mp, &newPoint );
   recreateSystemAfterSystemExists();
   realizeVelocity();
   p.updateGeometry(*_configState);
   return ret;
}

void OpenSimContext::setLocation(PathPoint& mp, int i, double d) {
    SimTK::Vec3 loc = mp.getLocation(*_configState);
    loc[i] = d;
    mp.setLocation(loc);
    recreateSystemKeepStage();
}

void OpenSimContext::setEndPoint(PathWrap& mw, int newEndPt) {
    mw.setEndPoint(*_configState, newEndPt );
    recreateSystemKeepStage();
    return;
}

void OpenSimContext::addPathPoint(GeometryPath& p, int menuChoice, PhysicalFrame&  body) {
    p.addPathPoint(*_configState, menuChoice, body );
    recreateSystemKeepStage();
    p.updateGeometry(*_configState);
    return;
}

bool OpenSimContext::deletePathPoint(GeometryPath& p, int menuChoice) {
    bool deletedSuccessfully = p.deletePathPoint(*_configState, menuChoice );
    if (deletedSuccessfully)
        recreateSystemKeepStage();
    return deletedSuccessfully;
}

bool OpenSimContext::isActivePathPoint(AbstractPathPoint& mp) {
  return mp.isActive(*_configState);
};

//_____________________________________________________________________________
/**
 * Replace one of the actuator's functions in the property array.
 *
 * @param aOldFunction the function being replaced.
 * @param aNewFunction the new function.
 */
void OpenSimContext::replacePropertyFunction(OpenSim::Object& obj, OpenSim::Function* aOldFunction, OpenSim::Function* aNewFunction)
{
  if (aOldFunction && aNewFunction) {
    PropertySet& propSet = obj.getPropertySet();

    for (int i=0; i <propSet.getSize(); i++) {
      Property_Deprecated* prop = propSet.get(i);
      if (prop->getType() == Property_Deprecated::ObjPtr) {
        if (prop->getValueObjPtr() == aOldFunction) {
          prop->setValue(aNewFunction);
        }
      }
    }
  }
}

// Muscle Wrapping
void OpenSimContext::setStartPoint(PathWrap& mw, int newStartPt) {
     mw.setStartPoint(*_configState, newStartPt );
     return;
}

void OpenSimContext::addPathWrap(GeometryPath& p, WrapObject& awo) {
    p.addPathWrap( awo );
    return;
}

void OpenSimContext::moveUpPathWrap(GeometryPath& p, int num) {
    p.moveUpPathWrap( *_configState, num );
    recreateSystemKeepStage();
    p.updateGeometry(*_configState);
    return;
}

void OpenSimContext::moveDownPathWrap(GeometryPath& p, int num) {
    p.moveDownPathWrap( *_configState, num );
    recreateSystemKeepStage();
    p.updateGeometry(*_configState);
    return;
}

void OpenSimContext::deletePathWrap(GeometryPath& p, int num) {
    p.deletePathWrap( *_configState, num );
    recreateSystemKeepStage();
    p.updateGeometry(*_configState);
    return;
}

// Markers
void OpenSimContext::setBody(Marker& currentMarker, PhysicalFrame&  newBody, bool b) {
    if( b ) {
         currentMarker.changeFramePreserveLocation( *_configState, newBody );
    } else {
         currentMarker.changeFrame( newBody );
    }
    return;
}

int OpenSimContext::replaceMarkerSet(Model& model, MarkerSet& aMarkerSet) {
  return model.replaceMarkerSet( *_configState, aMarkerSet);
}

// Analyses
int OpenSimContext::step(Analysis& analysis)
{
  return analysis.step( *_configState, 0);
}

// Tools
/*
bool OpenSimContext::initializeTrial(IKTool& ikTool, int i) {
  return ikTool.initializeTrial(*_configState, i);
}
*/
bool OpenSimContext::solveInverseKinematics( InverseKinematicsTool& ikTool) {
  return ikTool.run();
}

void OpenSimContext::setStatesFromMotion(AnalyzeTool& analyzeTool, const Storage &aMotion, bool aInDegrees) {
  analyzeTool.setStatesFromMotion(*_configState, aMotion, aInDegrees);
}

void OpenSimContext::loadStatesFromFile(AnalyzeTool& analyzeTool) {
  analyzeTool.loadStatesFromFile(*_configState);
}

bool OpenSimContext::processModelScale(ModelScaler& modelScaler,
                     Model* aModel,
                     const std::string& aPathToSubject,
                     double aFinalMass) {
  aModel->getMultibodySystem().realizeTopology();
    _configState=&aModel->updWorkingState();
  bool retValue= modelScaler.processModel(aModel, aPathToSubject, aFinalMass);
  // Model has changed need to recreate a valid state
  aModel->getMultibodySystem().realizeTopology();
    _configState=&aModel->updWorkingState();
  aModel->getMultibodySystem().realize(*_configState, SimTK::Stage::Position);
  return retValue;
}

bool OpenSimContext::processModelMarkerPlacer( MarkerPlacer& markerPlacer,
                        Model* aModel,
                        const std::string& aPathToSubject) {
  return markerPlacer.processModel(aModel, aPathToSubject);
}

double OpenSimContext::computeMeasurementScaleFactor(ModelScaler& modelScaler,
                           const Model& aModel,
                           const MarkerData& aMarkerData,
                           const Measurement& aMeasurement) const {
  return modelScaler.computeMeasurementScaleFactor(*_configState, aModel, aMarkerData, aMeasurement);
}

void OpenSimContext::replaceTransformAxisFunction(TransformAxis& aDof, OpenSim::Function& aFunction) {
   aDof.setFunction(&aFunction);
   this->recreateSystemAfterSystemExists();
   realizeVelocity();
}

// Force re-realization
void OpenSimContext::realizePosition() {
  _model->getMultibodySystem().realize(*_configState, SimTK::Stage::Position);

}
void OpenSimContext::realizeVelocity() {
  _model->getMultibodySystem().realize(*_configState, SimTK::Stage::Velocity);

}

void OpenSimContext::cacheModelAndState()
{
    clonedModel = _model->clone();
    clonedState = this->getCurrentStateCopy();
}

void OpenSimContext::restoreStateFromCachedModel()
{
    _model->initSystem();
    clonedModel->initSystem();

    Array<std::string> modelVariableNames = _model->getStateVariableNames();
    Array<std::string> clonedModelVariableNames = clonedModel->getStateVariableNames();

    for(int i = 0; i < modelVariableNames.getSize(); i++)
    {
        std::string name = modelVariableNames.get(i);
        if(clonedModelVariableNames.findIndex(name) >= 0)
        {
            double value = clonedModel->getStateVariableValue(clonedState, name);
            _model->setStateVariableValue(_model->updWorkingState(), name, value);
        }
    }
    this->setState(&(_model->updWorkingState()));
    this->realizePosition();
    delete clonedModel;
}
} // namespace
<|endoftext|>


<commit_before>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#include <cassert>
#include <stdexcept>
#include "TTFont.hpp"
#include "core/Engine.hpp"
#include "utils/Utf8.hpp"
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"

namespace ouzel
{
    namespace gui
    {
        TTFont::TTFont(const std::vector<uint8_t>& initData, bool initMipmaps):
            data(initData),
            mipmaps(initMipmaps)
        {
            const int offset = stbtt_GetFontOffsetForIndex(data.data(), 0);

            if (offset == -1)
                throw std::runtime_error("Not a font");

            font = std::make_unique<stbtt_fontinfo>();

            if (!stbtt_InitFont(font.get(), data.data(), offset))
                throw std::runtime_error("Failed to load font");
        }

        Font::RenderData TTFont::getRenderData(const std::string& text,
                                               Color color,
                                               float fontSize,
                                               const Vector2F& anchor) const
        {
            if (!font)
                throw std::runtime_error("Font not loaded");

            static constexpr uint32_t SPACING = 2;

            struct CharDescriptor final
            {
                uint16_t x = 0;
                uint16_t y = 0;
                uint16_t width = 0;
                uint16_t height = 0;
                Vector2F offset;
                float advance = 0;
                std::vector<uint8_t> bitmap;
            };

            std::unordered_map<uint32_t, CharDescriptor> chars;

            const float s = stbtt_ScaleForPixelHeight(font.get(), fontSize);

            const std::u32string utf32Text = utf8::toUtf32(text);

            std::set<char32_t> glyphs;
            for (const char32_t i : utf32Text)
                glyphs.insert(i);

            uint16_t width = 0;
            uint16_t height = 0;

            int ascent;
            int descent;
            int lineGap;
            stbtt_GetFontVMetrics(font.get(), &ascent, &descent, &lineGap);

            for (const char32_t c : glyphs)
            {
                int w;
                int h;
                int xoff;
                int yoff;

                if (const int index = stbtt_FindGlyphIndex(font.get(), static_cast<int>(c)))
                {
                    int advance;
                    int leftBearing;
                    stbtt_GetGlyphHMetrics(font.get(), index, &advance, &leftBearing);

                    CharDescriptor charDesc;

                    if (unsigned char* bitmap = stbtt_GetGlyphBitmapSubpixel(font.get(), s, s, 0.0F, 0.0F, index, &w, &h, &xoff, &yoff))
                    {
                        charDesc.width = static_cast<uint16_t>(w);
                        charDesc.height = static_cast<uint16_t>(h);
                        charDesc.offset.v[0] = static_cast<float>(leftBearing * s);
                        charDesc.offset.v[1] = static_cast<float>(yoff + (ascent - descent) * s);
                        charDesc.bitmap = std::vector<uint8_t>(bitmap, bitmap + h * w);
                        charDesc.x = width;

                        width += static_cast<uint16_t>(w);
                        height = height > static_cast<uint16_t>(h) ? height : static_cast<uint16_t>(h);

                        stbtt_FreeBitmap(bitmap, nullptr);
                    }

                    charDesc.advance = static_cast<float>(advance * s);

                    if (!chars.empty())
                        width += SPACING;

                    chars[c] = charDesc;
                }
            }

            std::vector<uint8_t> textureData(width * height * 4);

            for (uint16_t posX = 0; posX < width; ++posX)
            {
                for (uint16_t posY = 0; posY < height; ++posY)
                {
                    textureData[(posY * width + posX) * 4 + 0] = 255;
                    textureData[(posY * width + posX) * 4 + 1] = 255;
                    textureData[(posY * width + posX) * 4 + 2] = 255;
                    textureData[(posY * width + posX) * 4 + 3] = 0;
                }
            }

            for (const auto& c : chars)
            {
                const CharDescriptor& charDesc = c.second;

                for (uint16_t posX = 0; posX < charDesc.width; ++posX)
                {
                    for (uint16_t posY = 0; posY < charDesc.height; ++posY)
                    {
                        textureData[(posY * width + posX + charDesc.x) * 4 + 0] = 255;
                        textureData[(posY * width + posX + charDesc.x) * 4 + 1] = 255;
                        textureData[(posY * width + posX + charDesc.x) * 4 + 2] = 255;
                        textureData[(posY * width + posX + charDesc.x) * 4 + 3] = charDesc.bitmap[posY * charDesc.width + posX];
                    }
                }
            }

            RenderData result;

            auto texture = std::make_shared<graphics::Texture>(*engine->getRenderer(),
                                                               textureData,
                                                               Size2U(width, height), 0,
                                                               mipmaps ? 0 : 1);

            Vector2F position;

            std::vector<uint16_t> indices;
            std::vector<graphics::Vertex> vertices;
            indices.reserve(utf32Text.size() * 6);
            vertices.reserve(utf32Text.size() * 4);

            Vector2F textCoords[4];

            size_t firstChar = 0;

            for (auto i = utf32Text.begin(); i != utf32Text.end(); ++i)
            {
                auto iter = chars.find(*i);

                if (iter != chars.end())
                {
                    const CharDescriptor& f = iter->second;

                    auto startIndex = static_cast<uint16_t>(vertices.size());
                    indices.push_back(startIndex + 0);
                    indices.push_back(startIndex + 1);
                    indices.push_back(startIndex + 2);

                    indices.push_back(startIndex + 1);
                    indices.push_back(startIndex + 3);
                    indices.push_back(startIndex + 2);

                    Vector2F leftTop(f.x / static_cast<float>(width),
                                     f.y / static_cast<float>(height));

                    Vector2F rightBottom((f.x + f.width) / static_cast<float>(width),
                                         (f.y + f.height) / static_cast<float>(height));

                    textCoords[0] = Vector2F(leftTop.v[0], rightBottom.v[1]);
                    textCoords[1] = Vector2F(rightBottom.v[0], rightBottom.v[1]);
                    textCoords[2] = Vector2F(leftTop.v[0], leftTop.v[1]);
                    textCoords[3] = Vector2F(rightBottom.v[0], leftTop.v[1]);

                    vertices.emplace_back(Vector3F{position.v[0] + f.offset.v[0], -position.v[1] - f.offset.v[1] - f.height, 0.0F},
                                          color, textCoords[0], Vector3F{0.0F, 0.0F, -1.0F});
                    vertices.emplace_back(Vector3F{position.v[0] + f.offset.v[0] + f.width, -position.v[1] - f.offset.v[1] - f.height, 0.0F},
                                          color, textCoords[1], Vector3F{0.0F, 0.0F, -1.0F});
                    vertices.emplace_back(Vector3F{position.v[0] + f.offset.v[0], -position.v[1] - f.offset.v[1], 0.0F},
                                          color, textCoords[2], Vector3F{0.0F, 0.0F, -1.0F});
                    vertices.emplace_back(Vector3F{position.v[0] + f.offset.v[0] + f.width, -position.v[1] - f.offset.v[1], 0.0F},
                                          color, textCoords[3], Vector3F{0.0F, 0.0F, -1.0F});

                    if ((i + 1) != utf32Text.end())
                    {
                        const int kernAdvance = stbtt_GetCodepointKernAdvance(font.get(),
                                                                              static_cast<int>(*i),
                                                                              static_cast<int>(*(i + 1)));
                        position.v[0] += static_cast<float>(kernAdvance) * s;
                    }

                    position.v[0] += f.advance;
                }

                if (*i == static_cast<uint32_t>('\n') || // line feed
                    (i + 1) == utf32Text.end()) // end of string
                {
                    const float lineWidth = position.v[0];
                    position.v[0] = 0.0F;
                    position.v[1] += fontSize + lineGap;

                    for (size_t c = firstChar; c < vertices.size(); ++c)
                        vertices[c].position.v[0] -= lineWidth * anchor.v[0];

                    firstChar = vertices.size();
                }
            }

            const float textHeight = position.v[1];

            for (graphics::Vertex& vertex : vertices)
                vertex.position.v[1] += textHeight * (1.0F - anchor.v[1]);

            return std::make_tuple(std::move(indices), std::move(vertices), std::move(texture));
        }
    } // namespace gui
} // namespace ouzel
<commit_msg>Disable -Wold-style-cast for stb_truetype.h<commit_after>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#include <cassert>
#include <stdexcept>
#include "TTFont.hpp"
#include "core/Engine.hpp"
#include "utils/Utf8.hpp"

#if defined(__GNUC__)
#  pragma GCC diagnostic push
#  pragma GCC diagnostic ignored "-Wold-style-cast"
#endif

#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"

#if defined(__GNUC__)
#  pragma GCC diagnostic pop
#endif

namespace ouzel
{
    namespace gui
    {
        TTFont::TTFont(const std::vector<uint8_t>& initData, bool initMipmaps):
            data(initData),
            mipmaps(initMipmaps)
        {
            const int offset = stbtt_GetFontOffsetForIndex(data.data(), 0);

            if (offset == -1)
                throw std::runtime_error("Not a font");

            font = std::make_unique<stbtt_fontinfo>();

            if (!stbtt_InitFont(font.get(), data.data(), offset))
                throw std::runtime_error("Failed to load font");
        }

        Font::RenderData TTFont::getRenderData(const std::string& text,
                                               Color color,
                                               float fontSize,
                                               const Vector2F& anchor) const
        {
            if (!font)
                throw std::runtime_error("Font not loaded");

            static constexpr uint32_t SPACING = 2;

            struct CharDescriptor final
            {
                uint16_t x = 0;
                uint16_t y = 0;
                uint16_t width = 0;
                uint16_t height = 0;
                Vector2F offset;
                float advance = 0;
                std::vector<uint8_t> bitmap;
            };

            std::unordered_map<uint32_t, CharDescriptor> chars;

            const float s = stbtt_ScaleForPixelHeight(font.get(), fontSize);

            const std::u32string utf32Text = utf8::toUtf32(text);

            std::set<char32_t> glyphs;
            for (const char32_t i : utf32Text)
                glyphs.insert(i);

            uint16_t width = 0;
            uint16_t height = 0;

            int ascent;
            int descent;
            int lineGap;
            stbtt_GetFontVMetrics(font.get(), &ascent, &descent, &lineGap);

            for (const char32_t c : glyphs)
            {
                int w;
                int h;
                int xoff;
                int yoff;

                if (const int index = stbtt_FindGlyphIndex(font.get(), static_cast<int>(c)))
                {
                    int advance;
                    int leftBearing;
                    stbtt_GetGlyphHMetrics(font.get(), index, &advance, &leftBearing);

                    CharDescriptor charDesc;

                    if (unsigned char* bitmap = stbtt_GetGlyphBitmapSubpixel(font.get(), s, s, 0.0F, 0.0F, index, &w, &h, &xoff, &yoff))
                    {
                        charDesc.width = static_cast<uint16_t>(w);
                        charDesc.height = static_cast<uint16_t>(h);
                        charDesc.offset.v[0] = static_cast<float>(leftBearing * s);
                        charDesc.offset.v[1] = static_cast<float>(yoff + (ascent - descent) * s);
                        charDesc.bitmap = std::vector<uint8_t>(bitmap, bitmap + h * w);
                        charDesc.x = width;

                        width += static_cast<uint16_t>(w);
                        height = height > static_cast<uint16_t>(h) ? height : static_cast<uint16_t>(h);

                        stbtt_FreeBitmap(bitmap, nullptr);
                    }

                    charDesc.advance = static_cast<float>(advance * s);

                    if (!chars.empty())
                        width += SPACING;

                    chars[c] = charDesc;
                }
            }

            std::vector<uint8_t> textureData(width * height * 4);

            for (uint16_t posX = 0; posX < width; ++posX)
            {
                for (uint16_t posY = 0; posY < height; ++posY)
                {
                    textureData[(posY * width + posX) * 4 + 0] = 255;
                    textureData[(posY * width + posX) * 4 + 1] = 255;
                    textureData[(posY * width + posX) * 4 + 2] = 255;
                    textureData[(posY * width + posX) * 4 + 3] = 0;
                }
            }

            for (const auto& c : chars)
            {
                const CharDescriptor& charDesc = c.second;

                for (uint16_t posX = 0; posX < charDesc.width; ++posX)
                {
                    for (uint16_t posY = 0; posY < charDesc.height; ++posY)
                    {
                        textureData[(posY * width + posX + charDesc.x) * 4 + 0] = 255;
                        textureData[(posY * width + posX + charDesc.x) * 4 + 1] = 255;
                        textureData[(posY * width + posX + charDesc.x) * 4 + 2] = 255;
                        textureData[(posY * width + posX + charDesc.x) * 4 + 3] = charDesc.bitmap[posY * charDesc.width + posX];
                    }
                }
            }

            RenderData result;

            auto texture = std::make_shared<graphics::Texture>(*engine->getRenderer(),
                                                               textureData,
                                                               Size2U(width, height), 0,
                                                               mipmaps ? 0 : 1);

            Vector2F position;

            std::vector<uint16_t> indices;
            std::vector<graphics::Vertex> vertices;
            indices.reserve(utf32Text.size() * 6);
            vertices.reserve(utf32Text.size() * 4);

            Vector2F textCoords[4];

            size_t firstChar = 0;

            for (auto i = utf32Text.begin(); i != utf32Text.end(); ++i)
            {
                auto iter = chars.find(*i);

                if (iter != chars.end())
                {
                    const CharDescriptor& f = iter->second;

                    auto startIndex = static_cast<uint16_t>(vertices.size());
                    indices.push_back(startIndex + 0);
                    indices.push_back(startIndex + 1);
                    indices.push_back(startIndex + 2);

                    indices.push_back(startIndex + 1);
                    indices.push_back(startIndex + 3);
                    indices.push_back(startIndex + 2);

                    Vector2F leftTop(f.x / static_cast<float>(width),
                                     f.y / static_cast<float>(height));

                    Vector2F rightBottom((f.x + f.width) / static_cast<float>(width),
                                         (f.y + f.height) / static_cast<float>(height));

                    textCoords[0] = Vector2F(leftTop.v[0], rightBottom.v[1]);
                    textCoords[1] = Vector2F(rightBottom.v[0], rightBottom.v[1]);
                    textCoords[2] = Vector2F(leftTop.v[0], leftTop.v[1]);
                    textCoords[3] = Vector2F(rightBottom.v[0], leftTop.v[1]);

                    vertices.emplace_back(Vector3F{position.v[0] + f.offset.v[0], -position.v[1] - f.offset.v[1] - f.height, 0.0F},
                                          color, textCoords[0], Vector3F{0.0F, 0.0F, -1.0F});
                    vertices.emplace_back(Vector3F{position.v[0] + f.offset.v[0] + f.width, -position.v[1] - f.offset.v[1] - f.height, 0.0F},
                                          color, textCoords[1], Vector3F{0.0F, 0.0F, -1.0F});
                    vertices.emplace_back(Vector3F{position.v[0] + f.offset.v[0], -position.v[1] - f.offset.v[1], 0.0F},
                                          color, textCoords[2], Vector3F{0.0F, 0.0F, -1.0F});
                    vertices.emplace_back(Vector3F{position.v[0] + f.offset.v[0] + f.width, -position.v[1] - f.offset.v[1], 0.0F},
                                          color, textCoords[3], Vector3F{0.0F, 0.0F, -1.0F});

                    if ((i + 1) != utf32Text.end())
                    {
                        const int kernAdvance = stbtt_GetCodepointKernAdvance(font.get(),
                                                                              static_cast<int>(*i),
                                                                              static_cast<int>(*(i + 1)));
                        position.v[0] += static_cast<float>(kernAdvance) * s;
                    }

                    position.v[0] += f.advance;
                }

                if (*i == static_cast<uint32_t>('\n') || // line feed
                    (i + 1) == utf32Text.end()) // end of string
                {
                    const float lineWidth = position.v[0];
                    position.v[0] = 0.0F;
                    position.v[1] += fontSize + lineGap;

                    for (size_t c = firstChar; c < vertices.size(); ++c)
                        vertices[c].position.v[0] -= lineWidth * anchor.v[0];

                    firstChar = vertices.size();
                }
            }

            const float textHeight = position.v[1];

            for (graphics::Vertex& vertex : vertices)
                vertex.position.v[1] += textHeight * (1.0F - anchor.v[1]);

            return std::make_tuple(std::move(indices), std::move(vertices), std::move(texture));
        }
    } // namespace gui
} // namespace ouzel
<|endoftext|>