<commit_before>//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// TextureUploadBenchmark:
//   Performance test for uploading texture data.
//

#include "ANGLEPerfTest.h"

#include <iostream>
#include <random>
#include <sstream>

#include "test_utils/gl_raii.h"
#include "util/shader_utils.h"

namespace angle
{
constexpr unsigned int kIterationsPerStep = 64;

struct TextureUploadParams final : public RenderTestParams
{
    TextureUploadParams()
    {
        iterationsPerStep = kIterationsPerStep;
        trackGpuTime      = true;

        baseSize     = 2048;
        subImageSize = 64;

        webgl = false;
    }

    std::string suffix() const override;

    GLsizei baseSize;
    GLsizei subImageSize;

    bool webgl;
};

std::ostream &operator<<(std::ostream &os, const TextureUploadParams &params)
{
    os << params.suffix().substr(1);
    return os;
}

std::string TextureUploadParams::suffix() const
{
    std::stringstream strstr;

    strstr << RenderTestParams::suffix();

    if (webgl)
    {
        strstr << "_webgl";
    }

    return strstr.str();
}

class TextureUploadBenchmarkBase : public ANGLERenderTest,
                                   public ::testing::WithParamInterface<TextureUploadParams>
{
  public:
    TextureUploadBenchmarkBase(const char *benchmarkName);

    void initializeBenchmark() override;
    void destroyBenchmark() override;

  protected:
    void initShaders();

    GLuint mProgram;
    GLuint mPositionLoc;
    GLuint mSamplerLoc;
};

class TextureUploadSubImageBenchmark : public TextureUploadBenchmarkBase
{
  public:
    TextureUploadSubImageBenchmark() : TextureUploadBenchmarkBase("TexSubImage")
    {
        addExtensionPrerequisite("GL_EXT_texture_storage");
    }

    void drawBenchmark() override;
};

class TextureUploadFullMipBenchmark : public TextureUploadBenchmarkBase
{
  public:
    TextureUploadFullMipBenchmark() : TextureUploadBenchmarkBase("TextureUpload") {}

    void drawBenchmark() override;
};

TextureUploadBenchmarkBase::TextureUploadBenchmarkBase(const char *benchmarkName)
    : ANGLERenderTest(benchmarkName, GetParam()), mProgram(0u), mPositionLoc(-1), mSamplerLoc(-1)
{
    setWebGLCompatibilityEnabled(GetParam().webgl);
    setRobustResourceInit(GetParam().webgl);
}

void TextureUploadBenchmarkBase::initializeBenchmark()
{
    const auto &params = GetParam();

    initShaders();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());

    if (params.webgl)
    {
        glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");
    }

    ASSERT_GL_NO_ERROR();
}

void TextureUploadBenchmarkBase::initShaders()
{
    constexpr char kVS[] = R"(attribute vec4 a_position;
void main()
{
    gl_Position = a_position;
})";

    constexpr char kFS[] = R"(precision mediump float;
uniform sampler2D s_texture;
void main()
{
    gl_FragColor = texture2D(s_texture, vec2(0, 0));
})";

    mProgram = CompileProgram(kVS, kFS);
    ASSERT_NE(0u, mProgram);

    mPositionLoc = glGetAttribLocation(mProgram, "a_position");
    mSamplerLoc  = glGetUniformLocation(mProgram, "s_texture");
    glUseProgram(mProgram);

    glDisable(GL_DEPTH_TEST);

    ASSERT_GL_NO_ERROR();
}

void TextureUploadBenchmarkBase::destroyBenchmark()
{
    glDeleteProgram(mProgram);
}

void TextureUploadSubImageBenchmark::drawBenchmark()
{
    const auto &params = GetParam();

    std::vector<float> textureData(params.subImageSize * params.subImageSize * 4, 0.5);

    GLTexture tex;

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, params.baseSize, params.baseSize);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glUniform1i(mSamplerLoc, 0);

    ASSERT_GL_NO_ERROR();

    startGpuTimer();
    for (unsigned int iteration = 0; iteration < params.iterationsPerStep; ++iteration)
    {
        glTexSubImage2D(GL_TEXTURE_2D, 0, rand() % (params.baseSize - params.subImageSize),
                        rand() % (params.baseSize - params.subImageSize), params.subImageSize,
                        params.subImageSize, GL_RGBA, GL_UNSIGNED_BYTE, textureData.data());

        // Perform a draw just so the texture data is flushed.  With the position attributes not
        // set, a constant default value is used, resulting in a very cheap draw.
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
    stopGpuTimer();

    ASSERT_GL_NO_ERROR();
}

void TextureUploadFullMipBenchmark::drawBenchmark()
{
    const auto &params = GetParam();

    std::vector<float> textureData(params.baseSize * params.baseSize * 4, 0.5);

    startGpuTimer();
    for (size_t it = 0; it < params.iterationsPerStep; ++it)
    {
        GLTexture tex;

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, tex);

        // Stage data for all mips
        GLint mip = 0;
        for (GLsizei levelSize = params.baseSize; levelSize > 0; levelSize >>= 1)
        {
            glTexImage2D(GL_TEXTURE_2D, mip++, GL_RGBA, levelSize, levelSize, 0, GL_RGBA,
                         GL_UNSIGNED_BYTE, textureData.data());
        }

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glUniform1i(mSamplerLoc, 0);

        // Perform a draw just so the texture data is flushed.  With the position attributes not
        // set, a constant default value is used, resulting in a very cheap draw.
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
    stopGpuTimer();

    ASSERT_GL_NO_ERROR();
}

TextureUploadParams TextureUploadD3D11Params(bool webglCompat)
{
    TextureUploadParams params;
    params.eglParameters = egl_platform::D3D11();
    params.webgl         = webglCompat;
    return params;
}

TextureUploadParams TextureUploadOpenGLOrGLESParams(bool webglCompat)
{
    TextureUploadParams params;
    params.eglParameters = egl_platform::OPENGL_OR_GLES(false);
    params.webgl         = webglCompat;
    return params;
}

TextureUploadParams TextureUploadVulkanParams(bool webglCompat)
{
    TextureUploadParams params;
    params.eglParameters = egl_platform::VULKAN();
    params.webgl         = webglCompat;
    return params;
}

TEST_P(TextureUploadSubImageBenchmark, Run)
{
    run();
}

TEST_P(TextureUploadFullMipBenchmark, Run)
{
    run();
}

ANGLE_INSTANTIATE_TEST(TextureUploadSubImageBenchmark,
                       TextureUploadD3D11Params(false),
                       TextureUploadD3D11Params(true),
                       TextureUploadOpenGLOrGLESParams(false),
                       TextureUploadOpenGLOrGLESParams(true),
                       TextureUploadVulkanParams(false),
                       TextureUploadVulkanParams(true));

ANGLE_INSTANTIATE_TEST(TextureUploadFullMipBenchmark,
                       TextureUploadD3D11Params(false),
                       TextureUploadD3D11Params(true),
                       TextureUploadOpenGLOrGLESParams(false),
                       TextureUploadOpenGLOrGLESParams(true),
                       TextureUploadVulkanParams(false),
                       TextureUploadVulkanParams(true));
}  // namespace angle
<commit_msg>Fix OOM in TextureUpload perf test<commit_after>//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// TextureUploadBenchmark:
//   Performance test for uploading texture data.
//

#include "ANGLEPerfTest.h"

#include <iostream>
#include <random>
#include <sstream>

#include "test_utils/gl_raii.h"
#include "util/shader_utils.h"

namespace angle
{
constexpr unsigned int kIterationsPerStep = 64;

struct TextureUploadParams final : public RenderTestParams
{
    TextureUploadParams()
    {
        iterationsPerStep = kIterationsPerStep;
        trackGpuTime      = true;

        baseSize     = 1024;
        subImageSize = 64;

        webgl = false;
    }

    std::string suffix() const override;

    GLsizei baseSize;
    GLsizei subImageSize;

    bool webgl;
};

std::ostream &operator<<(std::ostream &os, const TextureUploadParams &params)
{
    os << params.suffix().substr(1);
    return os;
}

std::string TextureUploadParams::suffix() const
{
    std::stringstream strstr;

    strstr << RenderTestParams::suffix();

    if (webgl)
    {
        strstr << "_webgl";
    }

    return strstr.str();
}

class TextureUploadBenchmarkBase : public ANGLERenderTest,
                                   public ::testing::WithParamInterface<TextureUploadParams>
{
  public:
    TextureUploadBenchmarkBase(const char *benchmarkName);

    void initializeBenchmark() override;
    void destroyBenchmark() override;

  protected:
    void initShaders();

    GLuint mProgram;
    GLuint mPositionLoc;
    GLuint mSamplerLoc;
};

class TextureUploadSubImageBenchmark : public TextureUploadBenchmarkBase
{
  public:
    TextureUploadSubImageBenchmark() : TextureUploadBenchmarkBase("TexSubImage")
    {
        addExtensionPrerequisite("GL_EXT_texture_storage");
    }

    void drawBenchmark() override;
};

class TextureUploadFullMipBenchmark : public TextureUploadBenchmarkBase
{
  public:
    TextureUploadFullMipBenchmark() : TextureUploadBenchmarkBase("TextureUpload") {}

    void drawBenchmark() override;
};

TextureUploadBenchmarkBase::TextureUploadBenchmarkBase(const char *benchmarkName)
    : ANGLERenderTest(benchmarkName, GetParam()), mProgram(0u), mPositionLoc(-1), mSamplerLoc(-1)
{
    setWebGLCompatibilityEnabled(GetParam().webgl);
    setRobustResourceInit(GetParam().webgl);
}

void TextureUploadBenchmarkBase::initializeBenchmark()
{
    const auto &params = GetParam();

    initShaders();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());

    if (params.webgl)
    {
        glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");
    }

    ASSERT_GL_NO_ERROR();
}

void TextureUploadBenchmarkBase::initShaders()
{
    constexpr char kVS[] = R"(attribute vec4 a_position;
void main()
{
    gl_Position = a_position;
})";

    constexpr char kFS[] = R"(precision mediump float;
uniform sampler2D s_texture;
void main()
{
    gl_FragColor = texture2D(s_texture, vec2(0, 0));
})";

    mProgram = CompileProgram(kVS, kFS);
    ASSERT_NE(0u, mProgram);

    mPositionLoc = glGetAttribLocation(mProgram, "a_position");
    mSamplerLoc  = glGetUniformLocation(mProgram, "s_texture");
    glUseProgram(mProgram);

    glDisable(GL_DEPTH_TEST);

    ASSERT_GL_NO_ERROR();
}

void TextureUploadBenchmarkBase::destroyBenchmark()
{
    glDeleteProgram(mProgram);
}

void TextureUploadSubImageBenchmark::drawBenchmark()
{
    const auto &params = GetParam();

    std::vector<float> textureData(params.subImageSize * params.subImageSize * 4, 0.5);

    GLTexture tex;

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, params.baseSize, params.baseSize);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glUniform1i(mSamplerLoc, 0);

    ASSERT_GL_NO_ERROR();

    startGpuTimer();
    for (unsigned int iteration = 0; iteration < params.iterationsPerStep; ++iteration)
    {
        glTexSubImage2D(GL_TEXTURE_2D, 0, rand() % (params.baseSize - params.subImageSize),
                        rand() % (params.baseSize - params.subImageSize), params.subImageSize,
                        params.subImageSize, GL_RGBA, GL_UNSIGNED_BYTE, textureData.data());

        // Perform a draw just so the texture data is flushed.  With the position attributes not
        // set, a constant default value is used, resulting in a very cheap draw.
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
    stopGpuTimer();

    ASSERT_GL_NO_ERROR();
}

void TextureUploadFullMipBenchmark::drawBenchmark()
{
    const auto &params = GetParam();

    std::vector<float> textureData(params.baseSize * params.baseSize * 4, 0.5);

    startGpuTimer();
    for (size_t it = 0; it < params.iterationsPerStep; ++it)
    {
        GLTexture tex;

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, tex);

        // Stage data for all mips
        GLint mip = 0;
        for (GLsizei levelSize = params.baseSize; levelSize > 0; levelSize >>= 1)
        {
            glTexImage2D(GL_TEXTURE_2D, mip++, GL_RGBA, levelSize, levelSize, 0, GL_RGBA,
                         GL_UNSIGNED_BYTE, textureData.data());
        }

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glUniform1i(mSamplerLoc, 0);

        // Perform a draw just so the texture data is flushed.  With the position attributes not
        // set, a constant default value is used, resulting in a very cheap draw.
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
    stopGpuTimer();

    ASSERT_GL_NO_ERROR();
}

TextureUploadParams TextureUploadD3D11Params(bool webglCompat)
{
    TextureUploadParams params;
    params.eglParameters = egl_platform::D3D11();
    params.webgl         = webglCompat;
    return params;
}

TextureUploadParams TextureUploadOpenGLOrGLESParams(bool webglCompat)
{
    TextureUploadParams params;
    params.eglParameters = egl_platform::OPENGL_OR_GLES(false);
    params.webgl         = webglCompat;
    return params;
}

TextureUploadParams TextureUploadVulkanParams(bool webglCompat)
{
    TextureUploadParams params;
    params.eglParameters = egl_platform::VULKAN();
    params.webgl         = webglCompat;
    return params;
}

TEST_P(TextureUploadSubImageBenchmark, Run)
{
    run();
}

TEST_P(TextureUploadFullMipBenchmark, Run)
{
    run();
}

ANGLE_INSTANTIATE_TEST(TextureUploadSubImageBenchmark,
                       TextureUploadD3D11Params(false),
                       TextureUploadD3D11Params(true),
                       TextureUploadOpenGLOrGLESParams(false),
                       TextureUploadOpenGLOrGLESParams(true),
                       TextureUploadVulkanParams(false),
                       TextureUploadVulkanParams(true));

ANGLE_INSTANTIATE_TEST(TextureUploadFullMipBenchmark,
                       TextureUploadD3D11Params(false),
                       TextureUploadD3D11Params(true),
                       TextureUploadOpenGLOrGLESParams(false),
                       TextureUploadOpenGLOrGLESParams(true),
                       TextureUploadVulkanParams(false),
                       TextureUploadVulkanParams(true));
}  // namespace angle
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file Style.cxx
 ** Defines the font and colour style for a class of text.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "Style.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

Style::Style() {
	aliasOfDefaultFont = true;
	Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
	      Platform::DefaultFontSize(), 0, SC_CHARSET_DEFAULT,
	      false, false, false, false, caseMixed, true, true, false);
}

Style::Style(const Style &source) {
	Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
	      0, 0, 0,
	      false, false, false, false, caseMixed, true, true, false);
	fore.desired = source.fore.desired;
	back.desired = source.back.desired;
	characterSet = source.characterSet;
	bold = source.bold;
	italic = source.italic;
	size = source.size;
	eolFilled = source.eolFilled;
	underline = source.underline;
	caseForce = source.caseForce;
	visible = source.visible;
	changeable = source.changeable;
	hotspot = source.hotspot;
}

Style::~Style() {
	if (aliasOfDefaultFont)
		font.SetID(0);
	else
		font.Release();
	aliasOfDefaultFont = false;
}

Style &Style::operator=(const Style &source) {
	if (this == &source)
		return * this;
	Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
	      0, 0, SC_CHARSET_DEFAULT,
	      false, false, false, false, caseMixed, true, true, false);
	fore.desired = source.fore.desired;
	back.desired = source.back.desired;
	characterSet = source.characterSet;
	bold = source.bold;
	italic = source.italic;
	size = source.size;
	eolFilled = source.eolFilled;
	underline = source.underline;
	caseForce = source.caseForce;
	visible = source.visible;
	changeable = source.changeable;
	return *this;
}

void Style::Clear(ColourDesired fore_, ColourDesired back_, int size_,
                  const char *fontName_, int characterSet_,
                  bool bold_, bool italic_, bool eolFilled_,
                  bool underline_, ecaseForced caseForce_,
		  bool visible_, bool changeable_, bool hotspot_) {
	fore.desired = fore_;
	back.desired = back_;
	characterSet = characterSet_;
	bold = bold_;
	italic = italic_;
	size = size_;
	fontName = fontName_;
	eolFilled = eolFilled_;
	underline = underline_;
	caseForce = caseForce_;
	visible = visible_;
	changeable = changeable_;
	hotspot = hotspot_;
	if (aliasOfDefaultFont)
		font.SetID(0);
	else
		font.Release();
	aliasOfDefaultFont = false;
}

void Style::ClearTo(const Style &source) {
	Clear(
		source.fore.desired,
		source.back.desired,
		source.size,
		source.fontName,
		source.characterSet,
		source.bold,
		source.italic,
		source.eolFilled,
		source.underline,
		source.caseForce,
		source.visible,
		source.changeable,
		source.hotspot);
}

bool Style::EquivalentFontTo(const Style *other) const {
	if (bold != other->bold ||
	        italic != other->italic ||
	        size != other->size ||
	        characterSet != other->characterSet)
		return false;
	if (fontName == other->fontName)
		return true;
	if (!fontName)
		return false;
	if (!other->fontName)
		return false;
	return strcmp(fontName, other->fontName) == 0;
}

void Style::Realise(Surface &surface, int zoomLevel, Style *defaultStyle, int extraFontFlag) {
	sizeZoomed = size + zoomLevel;
	if (sizeZoomed <= 2)	// Hangs if sizeZoomed <= 1
		sizeZoomed = 2;

	if (aliasOfDefaultFont)
		font.SetID(0);
	else
		font.Release();
	int deviceHeight = surface.DeviceHeightFont(sizeZoomed);
	aliasOfDefaultFont = defaultStyle &&
	                     (EquivalentFontTo(defaultStyle) || !fontName);
	if (aliasOfDefaultFont) {
		font.SetID(defaultStyle->font.GetID());
	} else if (fontName) {
		font.Create(fontName, characterSet, deviceHeight, bold, italic, extraFontFlag);
	} else {
		font.SetID(0);
	}

	ascent = surface.Ascent(font);
	descent = surface.Descent(font);
	// Probably more typographically correct to include leading
	// but that means more complex drawing as leading must be erased
	//lineHeight = surface.ExternalLeading() + surface.Height();
	externalLeading = surface.ExternalLeading(font);
	lineHeight = surface.Height(font);
	aveCharWidth = surface.AverageCharWidth(font);
	spaceWidth = surface.WidthChar(font, ' ');
}
<commit_msg>More members initialised in constructor even though they will be filled in later by Realise.<commit_after>// Scintilla source code edit control
/** @file Style.cxx
 ** Defines the font and colour style for a class of text.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "Style.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

Style::Style() {
	aliasOfDefaultFont = true;
	Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
	      Platform::DefaultFontSize(), 0, SC_CHARSET_DEFAULT,
	      false, false, false, false, caseMixed, true, true, false);
}

Style::Style(const Style &source) {
	Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
	      0, 0, 0,
	      false, false, false, false, caseMixed, true, true, false);
	fore.desired = source.fore.desired;
	back.desired = source.back.desired;
	characterSet = source.characterSet;
	bold = source.bold;
	italic = source.italic;
	size = source.size;
	eolFilled = source.eolFilled;
	underline = source.underline;
	caseForce = source.caseForce;
	visible = source.visible;
	changeable = source.changeable;
	hotspot = source.hotspot;
}

Style::~Style() {
	if (aliasOfDefaultFont)
		font.SetID(0);
	else
		font.Release();
	aliasOfDefaultFont = false;
}

Style &Style::operator=(const Style &source) {
	if (this == &source)
		return * this;
	Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
	      0, 0, SC_CHARSET_DEFAULT,
	      false, false, false, false, caseMixed, true, true, false);
	fore.desired = source.fore.desired;
	back.desired = source.back.desired;
	characterSet = source.characterSet;
	bold = source.bold;
	italic = source.italic;
	size = source.size;
	eolFilled = source.eolFilled;
	underline = source.underline;
	caseForce = source.caseForce;
	visible = source.visible;
	changeable = source.changeable;
	return *this;
}

void Style::Clear(ColourDesired fore_, ColourDesired back_, int size_,
                  const char *fontName_, int characterSet_,
                  bool bold_, bool italic_, bool eolFilled_,
                  bool underline_, ecaseForced caseForce_,
		  bool visible_, bool changeable_, bool hotspot_) {
	fore.desired = fore_;
	back.desired = back_;
	characterSet = characterSet_;
	bold = bold_;
	italic = italic_;
	size = size_;
	fontName = fontName_;
	eolFilled = eolFilled_;
	underline = underline_;
	caseForce = caseForce_;
	visible = visible_;
	changeable = changeable_;
	hotspot = hotspot_;
	if (aliasOfDefaultFont)
		font.SetID(0);
	else
		font.Release();
	aliasOfDefaultFont = false;
	sizeZoomed = 2;
	lineHeight = 2;
	ascent = 1;
	descent = 1;
	externalLeading = 0;
	aveCharWidth = 1;
	spaceWidth = 1;
}

void Style::ClearTo(const Style &source) {
	Clear(
		source.fore.desired,
		source.back.desired,
		source.size,
		source.fontName,
		source.characterSet,
		source.bold,
		source.italic,
		source.eolFilled,
		source.underline,
		source.caseForce,
		source.visible,
		source.changeable,
		source.hotspot);
}

bool Style::EquivalentFontTo(const Style *other) const {
	if (bold != other->bold ||
	        italic != other->italic ||
	        size != other->size ||
	        characterSet != other->characterSet)
		return false;
	if (fontName == other->fontName)
		return true;
	if (!fontName)
		return false;
	if (!other->fontName)
		return false;
	return strcmp(fontName, other->fontName) == 0;
}

void Style::Realise(Surface &surface, int zoomLevel, Style *defaultStyle, int extraFontFlag) {
	sizeZoomed = size + zoomLevel;
	if (sizeZoomed <= 2)	// Hangs if sizeZoomed <= 1
		sizeZoomed = 2;

	if (aliasOfDefaultFont)
		font.SetID(0);
	else
		font.Release();
	int deviceHeight = surface.DeviceHeightFont(sizeZoomed);
	aliasOfDefaultFont = defaultStyle &&
	                     (EquivalentFontTo(defaultStyle) || !fontName);
	if (aliasOfDefaultFont) {
		font.SetID(defaultStyle->font.GetID());
	} else if (fontName) {
		font.Create(fontName, characterSet, deviceHeight, bold, italic, extraFontFlag);
	} else {
		font.SetID(0);
	}

	ascent = surface.Ascent(font);
	descent = surface.Descent(font);
	// Probably more typographically correct to include leading
	// but that means more complex drawing as leading must be erased
	//lineHeight = surface.ExternalLeading() + surface.Height();
	externalLeading = surface.ExternalLeading(font);
	lineHeight = surface.Height(font);
	aveCharWidth = surface.AverageCharWidth(font);
	spaceWidth = surface.WidthChar(font, ' ');
}
<|endoftext|>


<commit_before>#include "vtkBar.h"
#include "vtkBar2.h"
#include "vtkImageFoo.h"

int main( int argc, char *argv[] )
{
 vtkBar *bar = vtkBar::New();
 bar->PrintSelf();
 bar->Delete();

 vtkBar2 *bar2 = vtkBar2::New();
 bar2->PrintSelf();
 bar2->Delete();

 vtkImageFoo *imagefoo = vtkImageFoo::New();
 imagefoo->PrintSelf();
 imagefoo->Delete();

 return 0;
}

<commit_msg>PrintSelf fix<commit_after>#include "vtkBar.h"
#include "vtkBar2.h"
#include "vtkImageFoo.h"

int main( int argc, char *argv[] )
{
 vtkBar *bar = vtkBar::New();
 bar->Print(cout);
 bar->Delete();

 vtkBar2 *bar2 = vtkBar2::New();
 bar2->Print(cout);
 bar2->Delete();

 vtkImageFoo *imagefoo = vtkImageFoo::New();
 imagefoo->Print(cout);
 imagefoo->Delete();

 return 0;
}

<|endoftext|>


<commit_before>// Copyright 2010 The Native Client 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 "native_client/src/trusted/plugin/ppapi/file_downloader.h"

#include <stdio.h>
#include <string>

#include "native_client/src/include/portability_io.h"
#include "native_client/src/shared/platform/nacl_check.h"
#include "native_client/src/trusted/plugin/utility.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/dev/ppb_file_io_dev.h"
#include "ppapi/cpp/dev/file_ref_dev.h"
#include "ppapi/cpp/url_request_info.h"
#include "ppapi/cpp/url_response_info.h"

namespace {

const char* const kChromeExtensionScheme = "chrome-extension";
const int32_t kExtensionRequestStatusOk = 0;

// A helper function that tests to see if |url| is in the chrome-extension
// scheme.  Note that this routine assumes that the scheme part of |url| is
// all lower-case UTF8.
bool IsChromeExtensionUrl(const std::string& url) {
  // The scheme has to exist and be at the start of |url|.
  return url.find(kChromeExtensionScheme) == 0;
}
}

namespace plugin {

void FileDownloader::Initialize(pp::Instance* instance) {
  PLUGIN_PRINTF(("FileDownloader::FileDownloader (this=%p)\n",
                 static_cast<void*>(this)));
  CHECK(instance != NULL);
  CHECK(instance_ == NULL);
  if (instance == NULL)
    return;
  if (instance_ != NULL)
    return;  // Can only initialize once.
  instance_ = instance;
  callback_factory_.Initialize(this);
}

bool FileDownloader::Open(const nacl::string& url,
                          const pp::CompletionCallback& callback) {
  CHECK(instance_ != NULL);
  url_to_open_ = url;
  url_ = url;
  file_open_notify_callback_ = callback;
  // Reset the url loader and file reader.
  // Note that we have the only refernce to the underlying objects, so
  // this will implicitly close any pending IO and destroy them.
  url_loader_ = pp::URLLoader(instance_);
  file_reader_ = pp::FileIO_Dev(instance_);
  file_io_trusted_interface_ = static_cast<const PPB_FileIOTrusted_Dev*>(
      pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_DEV_INTERFACE));
  if (file_io_trusted_interface_ == NULL)
    return false;  // Interface not supported by our browser

  // Prepare the url request.
  pp::URLRequestInfo url_request(instance_);
  url_request.SetURL(url_);
  url_request.SetStreamToFile(true);

  // Request asynchronous download of the url providing an on-load callback.
  pp::CompletionCallback onload_callback =
      callback_factory_.NewCallback(&FileDownloader::URLLoadStartNotify);
  int32_t pp_error = url_loader_.Open(url_request, onload_callback);
  bool async_notify_ok = (pp_error == PP_ERROR_WOULDBLOCK);
  PLUGIN_PRINTF(("FileDownloader::Open (async_notify_ok=%d)\n",
                 async_notify_ok));
  if (!async_notify_ok) {
    // Call manually to free allocated memory and report errors.  This calls
    // |file_open_notify_callback_| with |pp_error| as the parameter.
    onload_callback.Run(pp_error);
  }
  return async_notify_ok;
}

int32_t FileDownloader::GetPOSIXFileDescriptor() {
  // Use the trusted interface to get the file descriptor.
  if (file_io_trusted_interface_ == NULL) {
    return NACL_NO_FILE_DESC;
  }
  int32_t file_desc = file_io_trusted_interface_->GetOSFileDescriptor(
      file_reader_.pp_resource());

#if NACL_WINDOWS
  // Convert the Windows HANDLE from Pepper to a POSIX file descriptor.
  int32_t posix_desc = _open_osfhandle(file_desc, _O_RDWR | _O_BINARY);
  if (posix_desc == -1) {
    // Close the Windows HANDLE if it can't be converted.
    CloseHandle(reinterpret_cast<HANDLE>(file_desc));
    return NACL_NO_FILE_DESC;
  }
  file_desc = posix_desc;
#endif

  return file_desc;
}

void FileDownloader::URLLoadStartNotify(int32_t pp_error) {
  PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (pp_error=%"
                 NACL_PRId32")\n", pp_error));
  if (pp_error != PP_OK) {  // Url loading failed.
    file_open_notify_callback_.Run(pp_error);
    return;
  }

  // Process the response, validating the headers to confirm successful loading.
  pp::URLResponseInfo url_response(url_loader_.GetResponseInfo());
  if (url_response.is_null()) {
    PLUGIN_PRINTF((
        "FileDownloader::URLLoadStartNotify (url_response=NULL)\n"));
    file_open_notify_callback_.Run(pp_error);
    return;
  }
  // Note that URLs in the chrome-extension scheme produce different error
  // codes than other schemes.  This is because chrome-extension URLs are
  // really a special kind of file scheme, and therefore do not produce HTTP
  // status codes.
  pp::Var full_url = url_response.GetURL();
  if (!full_url.is_string()) {
    PLUGIN_PRINTF((
        "FileDownloader::URLLoadStartNotify (url is not a string)\n"));
    file_open_notify_callback_.Run(pp_error);
    return;
  }
  bool status_ok = false;
  int32_t status_code = url_response.GetStatusCode();
  if (IsChromeExtensionUrl(full_url.AsString())) {
    PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (chrome-extension "
                   "response status_code=%"NACL_PRId32")\n", status_code));
    status_ok = (status_code == kExtensionRequestStatusOk);
  } else {
    PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (HTTP response "
                   "status_code=%"NACL_PRId32")\n", status_code));
    status_ok = (status_code == NACL_HTTP_STATUS_OK);
  }

  if (!status_ok) {
    file_open_notify_callback_.Run(pp_error);
    return;
  }

  // Finish streaming the body asynchronously providing a callback.
  pp::CompletionCallback onload_callback =
      callback_factory_.NewCallback(&FileDownloader::URLLoadFinishNotify);
  pp_error = url_loader_.FinishStreamingToFile(onload_callback);
  bool async_notify_ok = (pp_error == PP_ERROR_WOULDBLOCK);
  PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (async_notify_ok=%d)\n",
                 async_notify_ok));
  if (!async_notify_ok) {
    // Call manually to free allocated memory and report errors.  This calls
    // |file_open_notify_callback_| with |pp_error| as the parameter.
    onload_callback.Run(pp_error);
  }
}

void FileDownloader::URLLoadFinishNotify(int32_t pp_error) {
  PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (pp_error=%"
                 NACL_PRId32")\n", pp_error));
  if (pp_error != PP_OK) {  // Streaming failed.
    file_open_notify_callback_.Run(pp_error);
    return;
  }

  pp::URLResponseInfo url_response(url_loader_.GetResponseInfo());
  // Validated on load.
  CHECK(url_response.GetStatusCode() == NACL_HTTP_STATUS_OK ||
        url_response.GetStatusCode() == kExtensionRequestStatusOk);

  // Record the full url from the response.
  pp::Var full_url = url_response.GetURL();
  PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (full_url=%s)\n",
                 full_url.DebugString().c_str()));
  if (!full_url.is_string()) {
    file_open_notify_callback_.Run(pp_error);
    return;
  }
  url_ = full_url.AsString();

  // The file is now fully downloaded.
  pp::FileRef_Dev file(url_response.GetBodyAsFileRef());
  if (file.is_null()) {
    PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (file=NULL)\n"));
    file_open_notify_callback_.Run(pp_error);
    return;
  }

  // Open the file asynchronously providing a callback.
  pp::CompletionCallback onopen_callback =
      callback_factory_.NewCallback(&FileDownloader::FileOpenNotify);
  pp_error = file_reader_.Open(file, PP_FILEOPENFLAG_READ, onopen_callback);
  bool async_notify_ok = (pp_error == PP_ERROR_WOULDBLOCK);
  PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (async_notify_ok=%d)\n",
                 async_notify_ok));
  if (!async_notify_ok) {
    // Call manually to free allocated memory and report errors.  This calls
    // |file_open_notify_callback_| with |pp_error| as the parameter.
    onopen_callback.Run(pp_error);
  }
}

void FileDownloader::FileOpenNotify(int32_t pp_error) {
  PLUGIN_PRINTF(("FileDownloader::FileOpenNotify (pp_error=%"NACL_PRId32")\n",
                 pp_error));
  file_open_notify_callback_.Run(pp_error);
}

}  // namespace plugin
<commit_msg>Return PP_ERROR_FAILED instead of PP_OK for error cases in file_downloader.<commit_after>// Copyright (c) 2011 The Native Client 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 "native_client/src/trusted/plugin/ppapi/file_downloader.h"

#include <stdio.h>
#include <string>

#include "native_client/src/include/portability_io.h"
#include "native_client/src/shared/platform/nacl_check.h"
#include "native_client/src/trusted/plugin/utility.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/dev/ppb_file_io_dev.h"
#include "ppapi/cpp/dev/file_ref_dev.h"
#include "ppapi/cpp/url_request_info.h"
#include "ppapi/cpp/url_response_info.h"

namespace {

const char* const kChromeExtensionScheme = "chrome-extension";
const int32_t kExtensionRequestStatusOk = 0;

// A helper function that tests to see if |url| is in the chrome-extension
// scheme.  Note that this routine assumes that the scheme part of |url| is
// all lower-case UTF8.
bool IsChromeExtensionUrl(const std::string& url) {
  // The scheme has to exist and be at the start of |url|.
  return url.find(kChromeExtensionScheme) == 0;
}
}

namespace plugin {

void FileDownloader::Initialize(pp::Instance* instance) {
  PLUGIN_PRINTF(("FileDownloader::FileDownloader (this=%p)\n",
                 static_cast<void*>(this)));
  CHECK(instance != NULL);
  CHECK(instance_ == NULL);
  if (instance == NULL)
    return;
  if (instance_ != NULL)
    return;  // Can only initialize once.
  instance_ = instance;
  callback_factory_.Initialize(this);
}

bool FileDownloader::Open(const nacl::string& url,
                          const pp::CompletionCallback& callback) {
  CHECK(instance_ != NULL);
  url_to_open_ = url;
  url_ = url;
  file_open_notify_callback_ = callback;
  // Reset the url loader and file reader.
  // Note that we have the only refernce to the underlying objects, so
  // this will implicitly close any pending IO and destroy them.
  url_loader_ = pp::URLLoader(instance_);
  file_reader_ = pp::FileIO_Dev(instance_);
  file_io_trusted_interface_ = static_cast<const PPB_FileIOTrusted_Dev*>(
      pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_DEV_INTERFACE));
  if (file_io_trusted_interface_ == NULL)
    return false;  // Interface not supported by our browser

  // Prepare the url request.
  pp::URLRequestInfo url_request(instance_);
  url_request.SetURL(url_);
  url_request.SetStreamToFile(true);

  // Request asynchronous download of the url providing an on-load callback.
  pp::CompletionCallback onload_callback =
      callback_factory_.NewCallback(&FileDownloader::URLLoadStartNotify);
  int32_t pp_error = url_loader_.Open(url_request, onload_callback);
  bool async_notify_ok = (pp_error == PP_ERROR_WOULDBLOCK);
  PLUGIN_PRINTF(("FileDownloader::Open (async_notify_ok=%d)\n",
                 async_notify_ok));
  if (!async_notify_ok) {
    // Call manually to free allocated memory and report errors.  This calls
    // |file_open_notify_callback_| with |pp_error| as the parameter.
    onload_callback.Run(pp_error);
  }
  return async_notify_ok;
}

int32_t FileDownloader::GetPOSIXFileDescriptor() {
  // Use the trusted interface to get the file descriptor.
  if (file_io_trusted_interface_ == NULL) {
    return NACL_NO_FILE_DESC;
  }
  int32_t file_desc = file_io_trusted_interface_->GetOSFileDescriptor(
      file_reader_.pp_resource());

#if NACL_WINDOWS
  // Convert the Windows HANDLE from Pepper to a POSIX file descriptor.
  int32_t posix_desc = _open_osfhandle(file_desc, _O_RDWR | _O_BINARY);
  if (posix_desc == -1) {
    // Close the Windows HANDLE if it can't be converted.
    CloseHandle(reinterpret_cast<HANDLE>(file_desc));
    return NACL_NO_FILE_DESC;
  }
  file_desc = posix_desc;
#endif

  return file_desc;
}

void FileDownloader::URLLoadStartNotify(int32_t pp_error) {
  PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (pp_error=%"
                 NACL_PRId32")\n", pp_error));
  if (pp_error != PP_OK) {  // Url loading failed.
    file_open_notify_callback_.Run(pp_error);
    return;
  }

  // Process the response, validating the headers to confirm successful loading.
  pp::URLResponseInfo url_response(url_loader_.GetResponseInfo());
  if (url_response.is_null()) {
    PLUGIN_PRINTF((
        "FileDownloader::URLLoadStartNotify (url_response=NULL)\n"));
    file_open_notify_callback_.Run(PP_ERROR_FAILED);
    return;
  }
  // Note that URLs in the chrome-extension scheme produce different error
  // codes than other schemes.  This is because chrome-extension URLs are
  // really a special kind of file scheme, and therefore do not produce HTTP
  // status codes.
  pp::Var full_url = url_response.GetURL();
  if (!full_url.is_string()) {
    PLUGIN_PRINTF((
        "FileDownloader::URLLoadStartNotify (url is not a string)\n"));
    file_open_notify_callback_.Run(PP_ERROR_FAILED);
    return;
  }
  bool status_ok = false;
  int32_t status_code = url_response.GetStatusCode();
  if (IsChromeExtensionUrl(full_url.AsString())) {
    PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (chrome-extension "
                   "response status_code=%"NACL_PRId32")\n", status_code));
    status_ok = (status_code == kExtensionRequestStatusOk);
  } else {
    PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (HTTP response "
                   "status_code=%"NACL_PRId32")\n", status_code));
    status_ok = (status_code == NACL_HTTP_STATUS_OK);
  }

  if (!status_ok) {
    file_open_notify_callback_.Run(PP_ERROR_FAILED);
    return;
  }

  // Finish streaming the body asynchronously providing a callback.
  pp::CompletionCallback onload_callback =
      callback_factory_.NewCallback(&FileDownloader::URLLoadFinishNotify);
  pp_error = url_loader_.FinishStreamingToFile(onload_callback);
  bool async_notify_ok = (pp_error == PP_ERROR_WOULDBLOCK);
  PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (async_notify_ok=%d)\n",
                 async_notify_ok));
  if (!async_notify_ok) {
    // Call manually to free allocated memory and report errors.  This calls
    // |file_open_notify_callback_| with |pp_error| as the parameter.
    onload_callback.Run(pp_error);
  }
}

void FileDownloader::URLLoadFinishNotify(int32_t pp_error) {
  PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (pp_error=%"
                 NACL_PRId32")\n", pp_error));
  if (pp_error != PP_OK) {  // Streaming failed.
    file_open_notify_callback_.Run(pp_error);
    return;
  }

  pp::URLResponseInfo url_response(url_loader_.GetResponseInfo());
  // Validated on load.
  CHECK(url_response.GetStatusCode() == NACL_HTTP_STATUS_OK ||
        url_response.GetStatusCode() == kExtensionRequestStatusOk);

  // Record the full url from the response.
  pp::Var full_url = url_response.GetURL();
  PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (full_url=%s)\n",
                 full_url.DebugString().c_str()));
  if (!full_url.is_string()) {
    file_open_notify_callback_.Run(PP_ERROR_FAILED);
    return;
  }
  url_ = full_url.AsString();

  // The file is now fully downloaded.
  pp::FileRef_Dev file(url_response.GetBodyAsFileRef());
  if (file.is_null()) {
    PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (file=NULL)\n"));
    file_open_notify_callback_.Run(PP_ERROR_FAILED);
    return;
  }

  // Open the file asynchronously providing a callback.
  pp::CompletionCallback onopen_callback =
      callback_factory_.NewCallback(&FileDownloader::FileOpenNotify);
  pp_error = file_reader_.Open(file, PP_FILEOPENFLAG_READ, onopen_callback);
  bool async_notify_ok = (pp_error == PP_ERROR_WOULDBLOCK);
  PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (async_notify_ok=%d)\n",
                 async_notify_ok));
  if (!async_notify_ok) {
    // Call manually to free allocated memory and report errors.  This calls
    // |file_open_notify_callback_| with |pp_error| as the parameter.
    onopen_callback.Run(pp_error);
  }
}

void FileDownloader::FileOpenNotify(int32_t pp_error) {
  PLUGIN_PRINTF(("FileDownloader::FileOpenNotify (pp_error=%"NACL_PRId32")\n",
                 pp_error));
  file_open_notify_callback_.Run(pp_error);
}

}  // namespace plugin
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_ENTITY_HANDLER_HPP
#define RJ_GAME_ENTITY_HANDLER_HPP

#include "components/player.hpp"
#include "collision.hpp"
#include "entity.hpp"

#include <mlk/containers/container_utl.h>
#include <mlk/log/log.h>
#include <mlk/types/types.h>

#include <vector>

namespace rj
{
	template<typename T>
	using entity_ptr = mlk::sptr<T>;
	using entity_base_ptr = entity_ptr<entity_base>;
	using player_ptr = entity_ptr<player>;

	class entity_handler
	{
		rndr& m_render;

		player_ptr m_player{nullptr};
		std::vector<entity_base_ptr> m_entities;
		std::size_t m_max_entities;
		std::size_t m_current_id{0};

		static constexpr float m_despawn_zone{0.f};

	public:
		using iterator = std::vector<entity_base_ptr>::iterator;
		using const_iterator = std::vector<entity_base_ptr>::const_iterator;

		entity_handler(rndr& r, std::size_t max_entities = 1000) :
			m_render{r},
			m_max_entities{max_entities}
		{ }

		bool create_entity(const entity_base_ptr& e) noexcept
		{
			if(!this->is_entity_valid(e))
				return false;

			this->create_entity_impl(e); // add/create entity in handler
			return true;
		}

		bool create_entity(const player_ptr& p) noexcept
		{
			if(!this->is_entity_valid(p) || this->is_player_registered())
				return false;

			this->create_entity_impl(p);
			return true;
		}

		void update(dur duration)
		{
			// update player
			if(this->is_player_registered())
				m_player->update(duration);

			// update other
			for(auto& a : m_entities)
			{
				a->update(duration);
				if(a->right_out() <= m_despawn_zone)
					a->destroy();
			}

			this->check_collision();

			// erase flagged entities
			this->erase_destroyed();
		}

		void render()
		{
			// render player
			if(this->is_player_registered())
				m_player->render();

			// render other
			for(auto& a : m_entities)
				a->render();
		}

		void clear() noexcept
		{m_entities.clear();}

		void delete_entity(iterator iter)
		{m_entities.erase(iter);}

		bool exists_entity_at(const vec2f& at) noexcept
		{return this->get_entity_at(at) != std::end(m_entities);}

		iterator get_entity_at(const vec2f& at) noexcept
		{
			for(auto iter(std::begin(m_entities)); iter != std::end(m_entities); ++iter)
			{
				sf::FloatRect ent_bounds{{(*iter)->left_out(), (*iter)->top_out()}, (*iter)->size()};
				sf::FloatRect at_bounds{at, {1.f, 1.f}};
				if(ent_bounds.intersects(at_bounds))
					return iter;
			}
			return std::end(m_entities);
		}

		iterator begin()
		{return std::begin(m_entities);}

		iterator end()
		{return std::end(m_entities);}

		std::size_t num_entities() const noexcept
		{return m_entities.size() + this->is_player_registered();}

	private:
		void check_collision() noexcept
		{
			if(!this->is_player_registered())
				return;

			bool collided{false};

			for(auto& a : m_entities)
			{
				if(is_colliding(*m_player, *a))
				{
					collided = true;

					if(m_player->bottom_out() - 2 <= a->top_out())
					{
						m_player->on_collision(a->top_out());
						m_player->render_object().setFillColor({0, 255, 0});
					}
					else
						m_player->render_object().setFillColor({255, 0, 0});

					if(a->has_propertie(entity_propertie::death))
					{
						// player touched death entity
						m_player->render_object().setFillColor({255, 0, 0});
					}
				}
			}
			if(!collided)
				m_player->on_collision_end();
		}

		// checking the entities
		bool is_entity_valid(const entity_base_ptr& e) const noexcept
		{
			if(m_entities.size() >= m_max_entities)
			{
				mlk::lout("rj::entity_handler") << "max_entities limit is reached, can't add more entities";
				return false;
			}
			if(e->is_registered())
			{
				mlk::lout("rj::entity_handler") << "entity with id '" << e->m_id << "' exists already in entity handler, ignoring";
				return false;
			}
			return true;
		}

		bool is_player_registered() const noexcept
		{return m_player != nullptr;}

		// create the entities
		void create_entity_impl(const entity_base_ptr& e) noexcept
		{
			this->register_impl(e);
			m_entities.push_back(e);
		}

		void create_entity_impl(const player_ptr& p) noexcept
		{
			this->register_impl(p);
			m_player = p;
		}

		void register_impl(const entity_base_ptr& e) noexcept
		{
			// important: set game and init
			e->handler_register(&m_render, m_current_id);
			e->init();
			++m_current_id;
		}

		void erase_destroyed() noexcept
		{
			mlk::cnt::remove_all_if(
			[](const entity_base_ptr& entity){return entity->m_destroyed;}, m_entities);
		}
	};
}

#endif // RJ_GAME_ENTITY_HANDLER_HPP
<commit_msg>enitity_handler: get_entity_at -> get_entities_at delete_entity -> delete_entities added size param<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_ENTITY_HANDLER_HPP
#define RJ_GAME_ENTITY_HANDLER_HPP

#include "components/player.hpp"
#include "collision.hpp"
#include "entity.hpp"

#include <mlk/containers/container_utl.h>
#include <mlk/log/log.h>
#include <mlk/types/types.h>

#include <vector>

namespace rj
{
	template<typename T>
	using entity_ptr = mlk::sptr<T>;
	using entity_base_ptr = entity_ptr<entity_base>;
	using player_ptr = entity_ptr<player>;

	class entity_handler
	{
		rndr& m_render;

		player_ptr m_player{nullptr};
		std::vector<entity_base_ptr> m_entities;
		std::size_t m_max_entities;
		std::size_t m_current_id{0};

		static constexpr float m_despawn_zone{0.f};

	public:
		using iterator = std::vector<entity_base_ptr>::iterator;
		using const_iterator = std::vector<entity_base_ptr>::const_iterator;

		entity_handler(rndr& r, std::size_t max_entities = 1000) :
			m_render{r},
			m_max_entities{max_entities}
		{ }

		bool create_entity(const entity_base_ptr& e) noexcept
		{
			if(!this->is_entity_valid(e))
				return false;

			this->create_entity_impl(e); // add/create entity in handler
			return true;
		}

		bool create_entity(const player_ptr& p) noexcept
		{
			if(!this->is_entity_valid(p) || this->is_player_registered())
				return false;

			this->create_entity_impl(p);
			return true;
		}

		void update(dur duration)
		{
			// update player
			if(this->is_player_registered())
				m_player->update(duration);

			// update other
			for(auto& a : m_entities)
			{
				a->update(duration);
				if(a->right_out() <= m_despawn_zone)
					a->destroy();
			}

			this->check_collision();

			// erase flagged entities
			this->erase_destroyed();
		}

		void render()
		{
			// render player
			if(this->is_player_registered())
				m_player->render();

			// render other
			for(auto& a : m_entities)
				a->render();
		}

		void clear() noexcept
		{m_entities.clear();}

		// deleting ents on next update
		void delete_entities(std::vector<iterator>& iters)
		{for(auto& a : iters) (*a)->destroy();}

		std::vector<iterator> get_entities_at(const vec2f& at, const vec2f& size = {1.f, 1.f}) noexcept
		{
			std::vector<iterator> result;
			sf::FloatRect at_bounds{at, size};
			for(auto iter(std::begin(m_entities)); iter != std::end(m_entities); ++iter)
			{
				sf::FloatRect ent_bounds{{(*iter)->left_out(), (*iter)->top_out()}, (*iter)->size()};
				if(ent_bounds.intersects(at_bounds))
					result.emplace_back(iter);
			}
			return result;
		}

		bool exists_entity_at(const vec2f& at, const vec2f& size = {1.f, 1.f}) noexcept
		{return !this->get_entities_at(at, size).empty();}

		iterator begin()
		{return std::begin(m_entities);}

		iterator end()
		{return std::end(m_entities);}

		std::size_t num_entities() const noexcept
		{return m_entities.size() + this->is_player_registered();}

	private:
		void check_collision() noexcept
		{
			if(!this->is_player_registered())
				return;

			bool collided{false};

			for(auto& a : m_entities)
			{
				if(is_colliding(*m_player, *a))
				{
					collided = true;

					if(m_player->bottom_out() - 2 <= a->top_out())
					{
						m_player->on_collision(a->top_out());
						m_player->render_object().setFillColor({0, 255, 0});
					}
					else
						m_player->render_object().setFillColor({255, 0, 0});

					if(a->has_propertie(entity_propertie::death))
					{
						// player touched death entity
						m_player->render_object().setFillColor({255, 0, 0});
					}
				}
			}
			if(!collided)
				m_player->on_collision_end();
		}

		// checking the entities
		bool is_entity_valid(const entity_base_ptr& e) const noexcept
		{
			if(m_entities.size() >= m_max_entities)
			{
				mlk::lout("rj::entity_handler") << "max_entities limit is reached, can't add more entities";
				return false;
			}
			if(e->is_registered())
			{
				mlk::lout("rj::entity_handler") << "entity with id '" << e->m_id << "' exists already in entity handler, ignoring";
				return false;
			}
			return true;
		}

		bool is_player_registered() const noexcept
		{return m_player != nullptr;}

		// create the entities
		void create_entity_impl(const entity_base_ptr& e) noexcept
		{
			this->register_impl(e);
			m_entities.push_back(e);
		}

		void create_entity_impl(const player_ptr& p) noexcept
		{
			this->register_impl(p);
			m_player = p;
		}

		void register_impl(const entity_base_ptr& e) noexcept
		{
			// important: set game and init
			e->handler_register(&m_render, m_current_id);
			e->init();
			++m_current_id;
		}

		void erase_destroyed() noexcept
		{
			mlk::cnt::remove_all_if(
			[](const entity_base_ptr& entity){return entity->m_destroyed;}, m_entities);
		}
	};
}

#endif // RJ_GAME_ENTITY_HANDLER_HPP
<|endoftext|>


<commit_before>#pragma once

#include "boost_defs.hpp"

#include "grabbable_state_manager.hpp"
#include "grabber_client.hpp"
#include "hid_manager.hpp"
#include "hid_observer.hpp"
#include "logger.hpp"
#include "types.hpp"

namespace krbn {
class device_observer final {
public:
  device_observer(const device_observer&) = delete;

  device_observer(std::weak_ptr<grabber_client> grabber_client) : grabber_client_(grabber_client),
                                                                  hid_manager_({
                                                                      std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_keyboard),
                                                                      std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_mouse),
                                                                      std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_pointer),
                                                                  }) {
    grabbable_state_manager_.grabbable_state_changed.connect([this](auto&& grabbable_state) {
      if (auto client = grabber_client_.lock()) {
        client->grabbable_state_changed(grabbable_state);
      }
    });

    hid_manager_.device_detecting.connect([](auto&& device) {
      if (iokit_utility::is_karabiner_virtual_hid_device(device)) {
        return false;
      }

      iokit_utility::log_matching_device(device);

      return true;
    });

    hid_manager_.device_detected.connect([this](auto&& human_interface_device) {
      logger::get_logger().info("{0} is detected.", human_interface_device->get_name_for_log());

      grabbable_state_manager_.update(grabbable_state(human_interface_device->get_registry_entry_id(),
                                                      grabbable_state::state::device_error,
                                                      grabbable_state::ungrabbable_temporarily_reason::none,
                                                      mach_absolute_time()));

      human_interface_device->values_arrived.connect([this](auto&& human_interface_device,
                                                            auto&& event_queue) {
        grabbable_state_manager_.update(event_queue);
      });

      auto observer = std::make_shared<hid_observer>(human_interface_device);

      observer->device_observed.connect([this](auto&& human_interface_device) {
        logger::get_logger().info("{0} is observed.",
                                  human_interface_device->get_name_for_log());

        if (auto state = grabbable_state_manager_.get_grabbable_state(human_interface_device->get_registry_entry_id())) {
          // Keep grabbable_state if the state is already changed by value_callback.
          if (state->get_state() == grabbable_state::state::device_error) {
            grabbable_state_manager_.update(grabbable_state(human_interface_device->get_registry_entry_id(),
                                                            grabbable_state::state::grabbable,
                                                            grabbable_state::ungrabbable_temporarily_reason::none,
                                                            mach_absolute_time()));
          }
        }
      });

      observer->observe();

      hid_observers_[human_interface_device->get_registry_entry_id()] = observer;
    });

    hid_manager_.device_removed.connect([this](auto&& human_interface_device) {
      logger::get_logger().info("{0} is removed.", human_interface_device->get_name_for_log());

      hid_observers_.erase(human_interface_device->get_registry_entry_id());
    });

    hid_manager_.start();

    logger::get_logger().info("device_observer is started.");
  }

  ~device_observer(void) {
    hid_observers_.clear();
    hid_manager_.stop();

    logger::get_logger().info("device_observer is stopped.");
  }

private:
  std::weak_ptr<grabber_client> grabber_client_;

  hid_manager hid_manager_;
  std::unordered_map<registry_entry_id, std::shared_ptr<hid_observer>> hid_observers_;
  grabbable_state_manager grabbable_state_manager_;
};
} // namespace krbn
<commit_msg>add a comment<commit_after>#pragma once

// `krbn::device_observer` can be used safely in a multi-threaded environment.

#include "boost_defs.hpp"

#include "grabbable_state_manager.hpp"
#include "grabber_client.hpp"
#include "hid_manager.hpp"
#include "hid_observer.hpp"
#include "logger.hpp"
#include "types.hpp"

namespace krbn {
class device_observer final {
public:
  device_observer(const device_observer&) = delete;

  device_observer(std::weak_ptr<grabber_client> grabber_client) : grabber_client_(grabber_client),
                                                                  hid_manager_({
                                                                      std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_keyboard),
                                                                      std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_mouse),
                                                                      std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_pointer),
                                                                  }) {
    grabbable_state_manager_.grabbable_state_changed.connect([this](auto&& grabbable_state) {
      if (auto client = grabber_client_.lock()) {
        client->grabbable_state_changed(grabbable_state);
      }
    });

    hid_manager_.device_detecting.connect([](auto&& device) {
      if (iokit_utility::is_karabiner_virtual_hid_device(device)) {
        return false;
      }

      iokit_utility::log_matching_device(device);

      return true;
    });

    hid_manager_.device_detected.connect([this](auto&& human_interface_device) {
      logger::get_logger().info("{0} is detected.", human_interface_device->get_name_for_log());

      grabbable_state_manager_.update(grabbable_state(human_interface_device->get_registry_entry_id(),
                                                      grabbable_state::state::device_error,
                                                      grabbable_state::ungrabbable_temporarily_reason::none,
                                                      mach_absolute_time()));

      human_interface_device->values_arrived.connect([this](auto&& human_interface_device,
                                                            auto&& event_queue) {
        grabbable_state_manager_.update(event_queue);
      });

      auto observer = std::make_shared<hid_observer>(human_interface_device);

      observer->device_observed.connect([this](auto&& human_interface_device) {
        logger::get_logger().info("{0} is observed.",
                                  human_interface_device->get_name_for_log());

        if (auto state = grabbable_state_manager_.get_grabbable_state(human_interface_device->get_registry_entry_id())) {
          // Keep grabbable_state if the state is already changed by value_callback.
          if (state->get_state() == grabbable_state::state::device_error) {
            grabbable_state_manager_.update(grabbable_state(human_interface_device->get_registry_entry_id(),
                                                            grabbable_state::state::grabbable,
                                                            grabbable_state::ungrabbable_temporarily_reason::none,
                                                            mach_absolute_time()));
          }
        }
      });

      observer->observe();

      hid_observers_[human_interface_device->get_registry_entry_id()] = observer;
    });

    hid_manager_.device_removed.connect([this](auto&& human_interface_device) {
      logger::get_logger().info("{0} is removed.", human_interface_device->get_name_for_log());

      hid_observers_.erase(human_interface_device->get_registry_entry_id());
    });

    hid_manager_.start();

    logger::get_logger().info("device_observer is started.");
  }

  ~device_observer(void) {
    hid_observers_.clear();
    hid_manager_.stop();

    logger::get_logger().info("device_observer is stopped.");
  }

private:
  std::weak_ptr<grabber_client> grabber_client_;

  hid_manager hid_manager_;
  std::unordered_map<registry_entry_id, std::shared_ptr<hid_observer>> hid_observers_;
  grabbable_state_manager grabbable_state_manager_;
};
} // namespace krbn
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_SHARED_DATA_MANAGER_HPP
#define RJ_SHARED_DATA_MANAGER_HPP

#include <mlk/filesystem/filesystem.h>
#include <mlk/log/log.h>
#include <mlk/tools/compiletime.h>
#include <mlk/tools/stl_string_utl.h>
#include <mlk/types/types.h>

#include <map>

namespace rj
{
	using data_id = std::string;
	using data_vec = std::vector<mlk::data_packet>;

	class data_manager
	{
		mlk::fs::dir_handle m_dirh;
		mlk::fs::file_handle m_fileh;
		const std::string& m_abs_path;

		std::map<data_id, mlk::data_packet> m_data;

		bool m_valid{false};

	public:
		data_manager(const std::string& abs_datapath, bool auto_load = false) :
			m_dirh{abs_datapath},
			m_abs_path{m_dirh.get_path()},
			m_valid{m_dirh.exists()}
		{
			if(auto_load) this->load_all();
		}

		// interface
		// get:		don't loads the data to manager
		//			just 'gets' it
		auto get_all() const noexcept
		-> const decltype(m_data)&
		{return m_data;}

		mlk::data_packet get_raw(const data_id& id)
		{
			if(!this->exists_id(id))
				return {};
			return m_data[id];
		}

		data_vec get_all_containing_raw(const std::string& contain)
		{
			data_vec result;
			for(auto& a : m_data)
				if(mlk::stl_string::contains(contain, a.first))
					result.emplace_back(this->get_raw(a.first));
			return result;
		}

		template<typename T>
		T get_as(const data_id& id)
		{return this->get_as_impl<T>(id);}

		template<typename... Types, typename... Ids>
		std::tuple<Types...> get_multiple_as(Ids&&... ids)
		{
			static_assert(sizeof...(Types) == sizeof...(Ids), "Amount of types must match the amount of passed ids.");

			std::tuple<Types...> result;
			this->get_multiple_as_impl<mlk::get_upper(-1)>(result, std::forward<Ids>(ids)...);
			return result;
		}

		template<typename Type>
		std::vector<Type> get_all_containing_as(const std::string& contain)
		{
			std::vector<Type> result;
			for(auto& a : m_data)
				if(mlk::stl_string::contains(contain, a.first))
					result.emplace_back(this->get_as_impl<Type>(a.first));
			return result;
		}

		template<typename Type>
		std::map<data_id, Type> get_all_containing_as_map_as(const std::string& contain)
		{
			std::map<data_id, Type> result;
			for(auto& a : m_data)
				if(mlk::stl_string::contains(contain, a.first))
					result.emplace(a.first, this->get_as_impl<Type>(a.first));
			return result;

		}

		// load:	gets AND loads the data to manager
		mlk::data_packet load_raw(const data_id& id)
		{
			this->load_raw_impl(id, this->make_path(id));
			return m_data[id];
		}

		template<typename T>
		T load_as(const data_id& id)
		{return this->load_as_impl<T>(id);}

		template<typename... Types, typename... Ids>
		std::tuple<Types...> load_multiple_as(Ids&&... ids)
		{
			static_assert(sizeof...(Types) == sizeof...(Ids), "Amount of types must match the amount of passed ids.");

			std::tuple<Types...> result;
			this->load_multiple_as_impl<mlk::get_upper(-1)>(result, std::forward<Ids>(ids)...);
			return result;
		}

		bool exists_id(const data_id& id) const noexcept
		{return m_data.find(id) != std::end(m_data);}

		std::size_t num_data() const noexcept
		{return m_data.size();}

	private:
		// utils
		std::string make_path(const data_id& id)
		{return m_abs_path + id;}

		std::size_t get_datasize() const noexcept
		{
			std::size_t result{0};
			for(auto& a : m_data) result += a.second.size();
			return result;
		}

		// loads all data recursive
		// from absolute directory
		void load_all()
		{
			mlk::lout("rj::data_manager") << "loading files recursive from directory '" << m_abs_path << "'...";
			auto content(m_dirh.get_content<true>());
			auto count(0);
			for(auto& a : content)
				if(a.type == mlk::fs::item_type::file)
				{
					this->load_raw_impl(a.name, a.path);
					++count;
				}
			mlk::lout("rj::data_manager") << "loaded " << count << " files (" << this->get_datasize() << " bytes)";
		}

		// tuple impls
		template<int tup_index, typename Id_Head, typename... Types, typename... Id_Tail>
		void get_multiple_as_impl(std::tuple<Types...>& tup, const Id_Head& head, Id_Tail&&... tail)
		{
			std::get<tup_index>(tup) = this->get_as_impl<typename std::tuple_element<tup_index, std::tuple<Types...>>::type>(head);
			this->get_multiple_as_impl<mlk::get_upper(tup_index)>(tup, std::forward<Id_Tail>(tail)...);
		}

		template<int tup_index, typename... Types>
		void get_multiple_as_impl(std::tuple<Types...> &tup)
		{/* case: no args; do nothing */}

		template<int tup_index, typename Id_Head, typename... Types, typename... Id_Tail>
		void load_multiple_as_impl(std::tuple<Types...>& tup, const Id_Head& head, Id_Tail&&... tail)
		{
			std::get<tup_index>(tup) = this->load_as_impl<typename std::tuple_element<tup_index, std::tuple<Types...>>::type>(head);
			this->load_multiple_as_impl<mlk::get_upper(tup_index)>(tup, std::forward<Id_Tail>(tail)...);
		}

		template<int tup_index, typename... Types>
		void load_multiple_as_impl(std::tuple<Types...>& tup)
		{/* case: no args; do nothing */}

		// lowest level impls
		void load_raw_impl(const data_id& id, const std::string& path)
		{
			if(this->exists_id(id))
			{
				mlk::lerr()["rj::data_manager"] << "object with id '" << id << "' already loaded";
				return;
			}
			m_fileh.reopen(path, std::ios::in);
			m_data[id] = m_fileh.read_all();
			mlk::lout("rj::data_manager") << "loaded data '" << path << "'";
		}

		template<typename T>
		T load_as_impl(const data_id& id)
		{
			this->load_raw_impl(id, this->make_path(id));
			return this->get_as_impl<T>(id);
		}

		template<typename T>
		T get_as_impl(const data_id& id)
		{
			if(!this->exists_id(id))
			{
				mlk::lerr()["rj::data_manager"] << "object with id '" << id << "' not found";
				return T{};
			}
			T result;
			result.loadFromMemory(m_data[id].data(), m_data[id].size());
			return result;
		}
	};
}

#endif // RJ_SHARED_DATA_MANAGER_HPP
<commit_msg>data_manager: added exists_ids(...)<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_SHARED_DATA_MANAGER_HPP
#define RJ_SHARED_DATA_MANAGER_HPP

#include <mlk/filesystem/filesystem.h>
#include <mlk/log/log.h>
#include <mlk/tools/compiletime.h>
#include <mlk/tools/stl_string_utl.h>
#include <mlk/types/types.h>

#include <map>

namespace rj
{
	using data_id = std::string;
	using data_vec = std::vector<mlk::data_packet>;

	class data_manager
	{
		mlk::fs::dir_handle m_dirh;
		mlk::fs::file_handle m_fileh;
		const std::string& m_abs_path;

		std::map<data_id, mlk::data_packet> m_data;

		bool m_valid{false};

	public:
		data_manager(const std::string& abs_datapath, bool auto_load = false) :
			m_dirh{abs_datapath},
			m_abs_path{m_dirh.get_path()},
			m_valid{m_dirh.exists()}
		{
			if(auto_load) this->load_all();
		}

		// interface
		// get:		don't loads the data to manager
		//			just 'gets' it
		auto get_all() const noexcept
		-> const decltype(m_data)&
		{return m_data;}

		mlk::data_packet get_raw(const data_id& id)
		{
			if(!this->exists_id(id))
				return {};
			return m_data[id];
		}

		data_vec get_all_containing_raw(const std::string& contain)
		{
			data_vec result;
			for(auto& a : m_data)
				if(mlk::stl_string::contains(contain, a.first))
					result.emplace_back(this->get_raw(a.first));
			return result;
		}

		template<typename T>
		T get_as(const data_id& id)
		{return this->get_as_impl<T>(id);}

		template<typename... Types, typename... Ids>
		std::tuple<Types...> get_multiple_as(Ids&&... ids)
		{
			static_assert(sizeof...(Types) == sizeof...(Ids), "Amount of types must match the amount of passed ids.");

			std::tuple<Types...> result;
			this->get_multiple_as_impl<mlk::get_upper(-1)>(result, std::forward<Ids>(ids)...);
			return result;
		}

		template<typename Type>
		std::vector<Type> get_all_containing_as(const std::string& contain)
		{
			std::vector<Type> result;
			for(auto& a : m_data)
				if(mlk::stl_string::contains(contain, a.first))
					result.emplace_back(this->get_as_impl<Type>(a.first));
			return result;
		}

		template<typename Type>
		std::map<data_id, Type> get_all_containing_as_map_as(const std::string& contain)
		{
			std::map<data_id, Type> result;
			for(auto& a : m_data)
				if(mlk::stl_string::contains(contain, a.first))
					result.emplace(a.first, this->get_as_impl<Type>(a.first));
			return result;

		}

		// load:	gets AND loads the data to manager
		mlk::data_packet load_raw(const data_id& id)
		{
			this->load_raw_impl(id, this->make_path(id));
			return m_data[id];
		}

		template<typename T>
		T load_as(const data_id& id)
		{return this->load_as_impl<T>(id);}

		template<typename... Types, typename... Ids>
		std::tuple<Types...> load_multiple_as(Ids&&... ids)
		{
			static_assert(sizeof...(Types) == sizeof...(Ids), "Amount of types must match the amount of passed ids.");

			std::tuple<Types...> result;
			this->load_multiple_as_impl<mlk::get_upper(-1)>(result, std::forward<Ids>(ids)...);
			return result;
		}

		bool exists_id(const data_id& id) const noexcept
		{return m_data.find(id) != std::end(m_data);}

		bool exists_ids(const std::initializer_list<data_id>& il) const noexcept
		{
			for(auto& a : il)
				if(!mlk::cnt::exists_map_first(a, m_data))
					return false;
			return true;
		}

		std::size_t num_data() const noexcept
		{return m_data.size();}

	private:
		// utils
		std::string make_path(const data_id& id)
		{return m_abs_path + id;}

		std::size_t get_datasize() const noexcept
		{
			std::size_t result{0};
			for(auto& a : m_data) result += a.second.size();
			return result;
		}

		// loads all data recursive
		// from absolute directory
		void load_all()
		{
			mlk::lout("rj::data_manager") << "loading files recursive from directory '" << m_abs_path << "'...";
			auto content(m_dirh.get_content<true>());
			auto count(0);
			for(auto& a : content)
				if(a.type == mlk::fs::item_type::file)
				{
					this->load_raw_impl(a.name, a.path);
					++count;
				}
			mlk::lout("rj::data_manager") << "loaded " << count << " files (" << this->get_datasize() << " bytes)";
		}

		// tuple impls
		template<int tup_index, typename Id_Head, typename... Types, typename... Id_Tail>
		void get_multiple_as_impl(std::tuple<Types...>& tup, const Id_Head& head, Id_Tail&&... tail)
		{
			std::get<tup_index>(tup) = this->get_as_impl<typename std::tuple_element<tup_index, std::tuple<Types...>>::type>(head);
			this->get_multiple_as_impl<mlk::get_upper(tup_index)>(tup, std::forward<Id_Tail>(tail)...);
		}

		template<int tup_index, typename... Types>
		void get_multiple_as_impl(std::tuple<Types...> &tup)
		{/* case: no args; do nothing */}

		template<int tup_index, typename Id_Head, typename... Types, typename... Id_Tail>
		void load_multiple_as_impl(std::tuple<Types...>& tup, const Id_Head& head, Id_Tail&&... tail)
		{
			std::get<tup_index>(tup) = this->load_as_impl<typename std::tuple_element<tup_index, std::tuple<Types...>>::type>(head);
			this->load_multiple_as_impl<mlk::get_upper(tup_index)>(tup, std::forward<Id_Tail>(tail)...);
		}

		template<int tup_index, typename... Types>
		void load_multiple_as_impl(std::tuple<Types...>& tup)
		{/* case: no args; do nothing */}

		// lowest level impls
		void load_raw_impl(const data_id& id, const std::string& path)
		{
			if(this->exists_id(id))
			{
				mlk::lerr()["rj::data_manager"] << "object with id '" << id << "' already loaded";
				return;
			}
			m_fileh.reopen(path, std::ios::in);
			m_data[id] = m_fileh.read_all();
			mlk::lout("rj::data_manager") << "loaded data '" << path << "'";
		}

		template<typename T>
		T load_as_impl(const data_id& id)
		{
			this->load_raw_impl(id, this->make_path(id));
			return this->get_as_impl<T>(id);
		}

		template<typename T>
		T get_as_impl(const data_id& id)
		{
			if(!this->exists_id(id))
			{
				mlk::lerr()["rj::data_manager"] << "object with id '" << id << "' not found";
				return T{};
			}
			T result;
			result.loadFromMemory(m_data[id].data(), m_data[id].size());
			return result;
		}
	};
}

#endif // RJ_SHARED_DATA_MANAGER_HPP
<|endoftext|>


<commit_before>#include "hash.h"

unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash)
{
    // The following is MurmurHash3 (x86_32), see http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
    uint32_t h1 = nHashSeed;
    const uint32_t c1 = 0xcc9e2d51;
    const uint32_t c2 = 0x1b873593;

    const int nblocks = vDataToHash.size() / 4;

    //----------
    // body
    const uint32_t * blocks = (const uint32_t *)(&vDataToHash[0] + nblocks*4);

    for(int i = -nblocks; i; i++)
    {
        uint32_t k1 = blocks[i];

        k1 *= c1;
        k1 = ROTL32(k1,15);
        k1 *= c2;

        h1 ^= k1;
        h1 = ROTL32(h1,13);
        h1 = h1*5+0xe6546b64;
    }

    //----------
    // tail
    const uint8_t * tail = (const uint8_t*)(&vDataToHash[0] + nblocks*4);

    uint32_t k1 = 0;

    switch(vDataToHash.size() & 3)
    {
    case 3: k1 ^= tail[2] << 16;
    case 2: k1 ^= tail[1] << 8;
    case 1: k1 ^= tail[0];
            k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
    };

    //----------
    // finalization
    h1 ^= vDataToHash.size();
    h1 ^= h1 >> 16;
    h1 *= 0x85ebca6b;
    h1 ^= h1 >> 13;
    h1 *= 0xc2b2ae35;
    h1 ^= h1 >> 16;

    return h1;
}

int HMAC_SHA512_Init(HMAC_SHA512_CTX *pctx, const void *pkey, size_t len)
{
    unsigned char key[128];
    if (len <= 128)
    {
        memcpy(key, pkey, len);
        memset(key + len, 0, 128-len);
    }
    else
    {
        SHA512_CTX ctxKey;
        SHA512_Init(&ctxKey);
        SHA512_Update(&ctxKey, pkey, len);
        SHA512_Final(key, &ctxKey);
        memset(key + 64, 0, 64);
    }

    for (int n=0; n<128; n++)
        key[n] ^= 0x5c;
    SHA512_Init(&pctx->ctxOuter);
    SHA512_Update(&pctx->ctxOuter, key, 128);

    for (int n=0; n<128; n++)
        key[n] ^= 0x5c ^ 0x36;
    SHA512_Init(&pctx->ctxInner);
    return SHA512_Update(&pctx->ctxInner, key, 128);
}

int HMAC_SHA512_Update(HMAC_SHA512_CTX *pctx, const void *pdata, size_t len)
{
    return SHA512_Update(&pctx->ctxInner, pdata, len);
}

int HMAC_SHA512_Final(unsigned char *pmd, HMAC_SHA512_CTX *pctx)
{
    unsigned char buf[64];
    SHA512_Final(buf, &pctx->ctxInner);
    SHA512_Update(&pctx->ctxOuter, buf, 64);
    return SHA512_Final(pmd, &pctx->ctxOuter);
}
<commit_msg>hash checksums<commit_after>#include "hash.h"

unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash)
{
    // The following is MurmurHash3 (x86_32), see http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
    uint32_t h1 = nHashSeed;
    const uint32_t c1 = 0xcc9e2d51;
    const uint32_t c2 = 0x1b873593;

    const int nblocks = vDataToHash.size() / 4;

    //----------
    // body
    const uint32_t * blocks = (const uint32_t *)(&vDataToHash[0] + nblocks*4);

    for(int i = -nblocks; i; i++)
    {
        uint32_t k1 = blocks[i];

        k1 *= c1;
        k1 = ROTL32(k1,15);
        k1 *= c2;

        h1 ^= k1;
        h1 = ROTL32(h1,13);
        h1 = h1*5+0xe6546b64;
    }

    //----------
    // tail
    const uint8_t * tail = (const uint8_t*)(&vDataToHash[0] + nblocks*4);

    uint32_t k1 = 0;

    switch(vDataToHash.size() & 3)
    {
    case 3: k1 ^= tail[2] << 16;
    case 2: k1 ^= tail[1] << 8;
    case 1: k1 ^= tail[0];
            k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
    };

    //----------
    // finalization
    h1 ^= vDataToHash.size();
    h1 ^= h1 >> 16;
    h1 *= 0x85ebca6b;
    h1 ^= h1 >> 13;
    h1 *= 0xc2b2ae35;
    h1 ^= h1 >> 16;

    return h1;
}

int HMAC_SHA512_Init(HMAC_SHA512_CTX *pctx, const void *pkey, size_t len)
{
    unsigned char key[128];
    if (len <= 128)
    {
        memcpy(key, pkey, len);
        memset(key + len, 0, 128-len);
    }
    else
    {
        SHA512_CTX ctxKey;
        SHA512_Init(&ctxKey);
        SHA512_Update(&ctxKey, pkey, len);
        SHA512_Final(key, &ctxKey);
        memset(key + 64, 0, 64);
    }

    for (int n=0; n<128; n++)
        key[n] ^= 0x5c;
    SHA512_Init(&pctx->ctxOuter);
    SHA512_Update(&pctx->ctxOuter, key, 128);

    for (int n=0; n<128; n++)
        key[n] ^= 0x5c ^ 0x36;
    SHA512_Init(&pctx->ctxInner);
    return SHA512_Update(&pctx->ctxInner, key, 128);
}

int HMAC_SHA512_Update(HMAC_SHA512_CTX *pctx, const void *pdata, size_t len)
{
    return SHA512_Update(&pctx->ctxInner, pdata, len);
}

int HMAC_SHA512_Final(unsigned char *pmd, HMAC_SHA512_CTX *pctx)
{
    unsigned char buf[64];
    SHA512_Final(buf, &pctx->ctxInner);
    SHA512_Update(&pctx->ctxOuter, buf, 64);
    return SHA512_Final(pmd, &pctx->ctxOuter);
}

uint32_t BitcoinChecksum(uint8_t* p, uint32_t nBytes)
{
    if (!p || nBytes == 0)
        return 0;

    uint8_t hash1[32];
    SHA256(p, nBytes, (uint8_t*)hash1);
    uint8_t hash2[32];
    SHA256((uint8_t*)hash1, sizeof(hash1), (uint8_t*)hash2);

    // -- checksum is the 1st 4 bytes of the hash
    uint32_t checksum;
    memcpy(&checksum, &hash2[0], 4);

    return checksum;
};

void AppendChecksum(std::vector<uint8_t>& data)
{
    uint32_t checksum = BitcoinChecksum(&data[0], data.size());

    std::vector<uint8_t> tmp(4);
    memcpy(&tmp[0], &checksum, 4);

    data.insert(data.end(), tmp.begin(), tmp.end());
};

bool VerifyChecksum(const std::vector<uint8_t>& data)
{
    if (data.size() < 4)
        return false;

    uint32_t checksum;
    memcpy(&checksum, &(*(data.end() - 4)), 4);

    return BitcoinChecksum((uint8_t*)&data[0], data.size()-4) == checksum;
};
<|endoftext|>


<commit_before>// $Id$
// Author: Akira Okumura 2007/09/24

/******************************************************************************
 * Copyright (C) 2006-, Akira Okumura                                         *
 * All rights reserved.                                                       *
 *****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
//
// AOpticsManager
//
// Manager of optics
//
///////////////////////////////////////////////////////////////////////////////

#include "TRandom.h"
#include "RVersion.h"

#include "AOpticsManager.h"

#ifdef _OPENMP
#include <omp.h>
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,32,0)
#define MULTI_THREAD_NAVIGATION
#endif
#endif

static const Double_t kEpsilon = 1e-6; // Fixed in TGeoNavigator.cxx (equiv to 1e-6 cm)

ClassImp(AOpticsManager)

//_____________________________________________________________________________
AOpticsManager::AOpticsManager() : TGeoManager(), fDisableFresnelReflection(kFALSE)
{
  fLimit = 100;
  fNThreads = 1;
#ifdef MULTI_THREAD_NAVIGATION
  SetMultiThread(kTRUE);
#endif
}

//_____________________________________________________________________________
AOpticsManager::AOpticsManager(const char* name, const char* title)
 : TGeoManager(name, title), fDisableFresnelReflection(kFALSE)
{
  fLimit = 100;
  fNThreads = 1;
#ifdef MULTI_THREAD_NAVIGATION
  SetMultiThread(kTRUE);
#endif
}

//_____________________________________________________________________________
AOpticsManager::~AOpticsManager()
{
}

//_____________________________________________________________________________
void AOpticsManager::DoFresnel(Double_t n1, Double_t n2, ARay& ray)
{
  // Use the same notation used in Wikipedia
  // http://en.wikipedia.org/wiki/Fresnel_equations
  // theta_i = incident angle
  // theta_t = transmission angle
  Double_t* n = FindNormal(); // normal vect perpendicular to the surface
  Double_t cosi = fD1[0]*n[0] + fD1[1]*n[1] + fD1[2]*n[2]; // cos(theta_i)
  Double_t sini = TMath::Sqrt(1 - cosi*cosi);
  Double_t sint = n1*sini/n2; // Snell's law

  if(sint > 1.){ // total internal reflection
    fStep -= kEpsilon*2.; // stop the step before reaching the boundary
    DoReflection(n1, ray);
    return;
  } // if

  Double_t cost = TMath::Sqrt(1 - sint*sint);

  if(fDisableFresnelReflection == kFALSE){
    Double_t Rs = TMath::Power((n1*cosi - n2*cost)/(n1*cosi + n2*cost), 2); // reflectivity for s-polarized photon
    Double_t Rp = TMath::Power((n1*cost - n2*cosi)/(n1*cost + n2*cosi), 2); // reflectivity for p-polarized photon
    Double_t R = (Rs + Rp)/2.; // We assume that polarization is random

    if(gRandom->Uniform(1) < R){ // reflection at the boundary
      fStep -= kEpsilon*2.; // stop the step before reaching the boundary
      DoReflection(n1, ray);
      return;
    } // if
  } // if

  for(Int_t i = 0; i < 3; i++){
    fX2[i] = fX1[i] + fStep*fD1[i];
    fD2[i] = (fD1[i] - cosi*n[i])*sint/sini + n[i]*cost;
  } // i
  ray.SetDirection(fD2);

  // step (m), c (m/s)
  Double_t speed = TMath::C()*m()/n1;
  fX2[3] = fX1[3] + fStep/speed;
  ray.AddPoint(fX2[0], fX2[1], fX2[2], fX2[3]);
}

//_____________________________________________________________________________
void AOpticsManager::DoReflection(Double_t n1, ARay& ray)
{
  Double_t* n = FindNormal(); // normal vect perpendicular to the surface
  Double_t cosi = fD1[0]*n[0] + fD1[1]*n[1] + fD1[2]*n[2];

  Bool_t absorbed = kFALSE;

  if(fTypeEnd == kMirror){
    Double_t angle = TMath::ACos(cosi)*TMath::RadToDeg();
    Double_t lambda = ray.GetLambda();
    Double_t ref = ((AMirror*)fEndNode->GetVolume())->GetReflectivity(lambda, angle);
    if(ref < gRandom->Uniform(1)){
      absorbed = kTRUE;
      ray.Absorb();
    } // if
  } // if

  for(Int_t i = 0; i < 3; i++){ // d2 = d1 - 2n*(d1*n)
    fX2[i] = fX1[i] + fStep*fD1[i];
    fD2[i] = fD1[i] - 2*n[i]*cosi;
  } // i
  if(not absorbed){
    ray.SetDirection(fD2);
  } // if

  // step (m), c (m/s)
  Double_t speed = TMath::C()*m()/n1;
  fX2[3] = fX1[3] + fStep/speed;
  ray.AddPoint(fX2[0], fX2[1], fX2[2], fX2[3]);
}

//_____________________________________________________________________________
void AOpticsManager::TraceNonSequential(ARay& ray)
{
  Double_t lambda = ray.GetLambda();
  while(ray.IsRunning()){
    //Double_t fX1[4]; // start point
    //Double_t fX2[3]; // end point
    //Double_t fD1[3]; // start direction
    //Double_t fD2[3]; // end direction
    ray.GetLastPoint(fX1);
    ray.GetDirection(fD1);

    fStartNode = InitTrack(fX1, fD1); // start node
    if(IsOutside()){ // if the current position is outside of top volume
      fStartNode = 0;
    } // if

    fEndNode = FindNextBoundaryAndStep();

    // Check type of start node
    if     (                  !fStartNode)  fTypeStart = kNull;
    else if(            IsLens(fStartNode)) fTypeStart = kLens;
    else if(     IsObscuration(fStartNode)) fTypeStart = kObs;
    else if(          IsMirror(fStartNode)) fTypeStart = kMirror;
    else if(IsOpticalComponent(fStartNode)) fTypeStart = kOpt;
    else if(    IsFocalSurface(fStartNode)) fTypeStart = kFocus;
    else                                    fTypeStart = kOther;

    // Check type of end node
    if     (                  !fEndNode)  fTypeEnd = kNull;
    else if(            IsLens(fEndNode)) fTypeEnd = kLens;
    else if(     IsObscuration(fEndNode)) fTypeEnd = kObs;
    else if(          IsMirror(fEndNode)) fTypeEnd = kMirror;
    else if(IsOpticalComponent(fEndNode)) fTypeEnd = kOpt;
    else if(    IsFocalSurface(fEndNode)) fTypeEnd = kFocus;
    else                                  fTypeEnd = kOther;

    fStep = GetStep(); // distance to the next boundary
    if(fTypeEnd == kMirror){
      fStep -= kEpsilon; // make sure that the photon do NOT cross the boundary
    } else {
      fStep += kEpsilon; // make sure that the photon crosses the boundary
    } // if

    if(fTypeStart == kLens){
      Double_t abs = ((ALens*)fStartNode->GetVolume())->GetAbsorptionLength(lambda);
      if(abs > 0){
        Double_t abs_step = gRandom->Exp(abs);
        if(abs_step < fStep){
          Double_t n1 = ((ALens*)fStartNode->GetVolume())->GetRefractiveIndex(ray.GetLambda());
          Double_t speed = TMath::C()*m()/n1;
          ray.AddPoint(fX1[0] + fD1[0]*abs_step, fX1[1] + fD1[1]*abs_step, fX1[2] + fD1[2]*abs_step, fX1[3] + abs_step/speed);
          ray.Absorb();
          continue;
        } // if
      } // if
    } // if

    if((fTypeStart == kNull or fTypeStart == kOpt or fTypeStart == kLens or fTypeStart == kOther)
       and fTypeEnd == kMirror){
      Double_t n1 = fTypeStart == kLens ? ((ALens*)fStartNode->GetVolume())->GetRefractiveIndex(ray.GetLambda()) : 1.;
      DoReflection(n1, ray);
    } else if((fTypeStart == kNull or fTypeStart == kOpt or fTypeStart == kOther)
               and fTypeEnd == kLens){
      Double_t n1 = 1; // Assume refractive index equals 1 (= vacuum)
      Double_t n2 = ((ALens*)fEndNode->GetVolume())->GetRefractiveIndex(ray.GetLambda());
      DoFresnel(n1, n2, ray);
    } else if((fTypeStart == kNull or fTypeStart == kLens or fTypeStart == kOpt or fTypeStart == kOther)
               and (fTypeEnd == kObs or fTypeEnd == kFocus)){

      for(Int_t i = 0; i < 3; i++){
        fX2[i] = fX1[i] + fStep*fD1[i];
      } // i
      if (fTypeStart == kLens){
        Double_t n1 = ((ALens*)fStartNode->GetVolume())->GetRefractiveIndex(ray.GetLambda());
        Double_t speed = TMath::C()*m()/n1;
        fX2[3] = fX1[3] + fStep/speed;
      } else {
        Double_t speed = TMath::C()*m();
        fX2[3] = fX1[3] + fStep/speed;
      } // if
      ray.AddPoint(fX2[0], fX2[1], fX2[2], fX2[3]);
    } else if((fTypeStart == kNull or fTypeStart == kOpt or fTypeStart == kOther)
               and (fTypeEnd == kOther or fTypeEnd == kOpt)){

      for(Int_t i = 0; i < 3; i++){
        fX2[i] = fX1[i] + fStep*fD1[i];
      } // i
      Double_t speed = TMath::C()*m();
      fX2[3] = fX1[3] + fStep/speed;
      ray.AddPoint(fX2[0], fX2[1], fX2[2], fX2[3]);
    } else if(fTypeStart == kLens and fTypeEnd == kLens){
      Double_t n1 = ((ALens*)fStartNode->GetVolume())->GetRefractiveIndex(lambda);
      Double_t n2 = ((ALens*)fEndNode->GetVolume())->GetRefractiveIndex(lambda);
      DoFresnel(n1, n2, ray);
    } else if(fTypeStart == kLens and
              (fTypeEnd == kNull or fTypeEnd == kOpt or fTypeEnd == kOther)){
      Double_t n1 = ((ALens*)fStartNode->GetVolume())->GetRefractiveIndex(lambda);
      Double_t n2 = 1; // Assume refractive index equals 1 (= vacuum)
      DoFresnel(n1, n2, ray);
    } // if

    if(fTypeEnd == kNull){
      for(Int_t i = 0; i < 3; i++){
        fX2[i] = fX1[i] + fStep*fD1[i];
      } // i
      Double_t speed = TMath::C()*m();
      fX2[3] = fX1[3] + fStep/speed;
      ray.AddPoint(fX2[0], fX2[1], fX2[2], fX2[3]);
      ray.Exit();
    } else if(fTypeStart == kFocus or fTypeStart == kObs or fTypeStart == kMirror or fTypeEnd == kObs){
      ray.Stop();
    } else if(fTypeEnd == kFocus){
      ray.Focus();
    } // if

    if(ray.IsRunning() and ray.GetNpoints() >= fLimit){
      ray.Suspend();
    } // if

  } // while
}

//_____________________________________________________________________________
void AOpticsManager::TraceNonSequential(ARayArray& array)
{
  TObjArray* running = array.GetRunning();

#ifdef MULTI_THREAD_NAVIGATION
  omp_set_num_threads(fNThreads);
#pragma omp parallel
#pragma omp parallel for
#endif
  for(Int_t i = 0; i <= running->GetLast(); i++){
    ARay* ray = (ARay*)(*running)[i];
    if(!ray) continue;

    ray = (ARay*)running->RemoveAt(i);
    TraceNonSequential(*ray);
    array.Add(ray);
  } // i
}

//_____________________________________________________________________________
void AOpticsManager::SetLimit(Int_t n)
{
  if(n > 0){
    fLimit = n;
  } // if
}
<commit_msg>cd:  changed root version from 32 to 34 to avoid multithreading<commit_after>// $Id$
// Author: Akira Okumura 2007/09/24

/******************************************************************************
 * Copyright (C) 2006-, Akira Okumura                                         *
 * All rights reserved.                                                       *
 *****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
//
// AOpticsManager
//
// Manager of optics
//
///////////////////////////////////////////////////////////////////////////////

#include "TRandom.h"
#include "RVersion.h"

#include "AOpticsManager.h"

#ifdef _OPENMP
#include <omp.h>
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,34,0)
#define MULTI_THREAD_NAVIGATION
#endif
#endif

static const Double_t kEpsilon = 1e-6; // Fixed in TGeoNavigator.cxx (equiv to 1e-6 cm)

ClassImp(AOpticsManager)

//_____________________________________________________________________________
AOpticsManager::AOpticsManager() : TGeoManager(), fDisableFresnelReflection(kFALSE)
{
  fLimit = 100;
  fNThreads = 1;
#ifdef MULTI_THREAD_NAVIGATION
  SetMultiThread(kTRUE);
#endif
}

//_____________________________________________________________________________
AOpticsManager::AOpticsManager(const char* name, const char* title)
 : TGeoManager(name, title), fDisableFresnelReflection(kFALSE)
{
  fLimit = 100;
  fNThreads = 1;
#ifdef MULTI_THREAD_NAVIGATION
  SetMultiThread(kTRUE);
#endif
}

//_____________________________________________________________________________
AOpticsManager::~AOpticsManager()
{
}

//_____________________________________________________________________________
void AOpticsManager::DoFresnel(Double_t n1, Double_t n2, ARay& ray)
{
  // Use the same notation used in Wikipedia
  // http://en.wikipedia.org/wiki/Fresnel_equations
  // theta_i = incident angle
  // theta_t = transmission angle
  Double_t* n = FindNormal(); // normal vect perpendicular to the surface
  Double_t cosi = fD1[0]*n[0] + fD1[1]*n[1] + fD1[2]*n[2]; // cos(theta_i)
  Double_t sini = TMath::Sqrt(1 - cosi*cosi);
  Double_t sint = n1*sini/n2; // Snell's law

  if(sint > 1.){ // total internal reflection
    fStep -= kEpsilon*2.; // stop the step before reaching the boundary
    DoReflection(n1, ray);
    return;
  } // if

  Double_t cost = TMath::Sqrt(1 - sint*sint);

  if(fDisableFresnelReflection == kFALSE){
    Double_t Rs = TMath::Power((n1*cosi - n2*cost)/(n1*cosi + n2*cost), 2); // reflectivity for s-polarized photon
    Double_t Rp = TMath::Power((n1*cost - n2*cosi)/(n1*cost + n2*cosi), 2); // reflectivity for p-polarized photon
    Double_t R = (Rs + Rp)/2.; // We assume that polarization is random

    if(gRandom->Uniform(1) < R){ // reflection at the boundary
      fStep -= kEpsilon*2.; // stop the step before reaching the boundary
      DoReflection(n1, ray);
      return;
    } // if
  } // if

  for(Int_t i = 0; i < 3; i++){
    fX2[i] = fX1[i] + fStep*fD1[i];
    fD2[i] = (fD1[i] - cosi*n[i])*sint/sini + n[i]*cost;
  } // i
  ray.SetDirection(fD2);

  // step (m), c (m/s)
  Double_t speed = TMath::C()*m()/n1;
  fX2[3] = fX1[3] + fStep/speed;
  ray.AddPoint(fX2[0], fX2[1], fX2[2], fX2[3]);
}

//_____________________________________________________________________________
void AOpticsManager::DoReflection(Double_t n1, ARay& ray)
{
  Double_t* n = FindNormal(); // normal vect perpendicular to the surface
  Double_t cosi = fD1[0]*n[0] + fD1[1]*n[1] + fD1[2]*n[2];

  Bool_t absorbed = kFALSE;

  if(fTypeEnd == kMirror){
    Double_t angle = TMath::ACos(cosi)*TMath::RadToDeg();
    Double_t lambda = ray.GetLambda();
    Double_t ref = ((AMirror*)fEndNode->GetVolume())->GetReflectivity(lambda, angle);
    if(ref < gRandom->Uniform(1)){
      absorbed = kTRUE;
      ray.Absorb();
    } // if
  } // if

  for(Int_t i = 0; i < 3; i++){ // d2 = d1 - 2n*(d1*n)
    fX2[i] = fX1[i] + fStep*fD1[i];
    fD2[i] = fD1[i] - 2*n[i]*cosi;
  } // i
  if(not absorbed){
    ray.SetDirection(fD2);
  } // if

  // step (m), c (m/s)
  Double_t speed = TMath::C()*m()/n1;
  fX2[3] = fX1[3] + fStep/speed;
  ray.AddPoint(fX2[0], fX2[1], fX2[2], fX2[3]);
}

//_____________________________________________________________________________
void AOpticsManager::TraceNonSequential(ARay& ray)
{
  Double_t lambda = ray.GetLambda();
  while(ray.IsRunning()){
    //Double_t fX1[4]; // start point
    //Double_t fX2[3]; // end point
    //Double_t fD1[3]; // start direction
    //Double_t fD2[3]; // end direction
    ray.GetLastPoint(fX1);
    ray.GetDirection(fD1);

    fStartNode = InitTrack(fX1, fD1); // start node
    if(IsOutside()){ // if the current position is outside of top volume
      fStartNode = 0;
    } // if

    fEndNode = FindNextBoundaryAndStep();

    // Check type of start node
    if     (                  !fStartNode)  fTypeStart = kNull;
    else if(            IsLens(fStartNode)) fTypeStart = kLens;
    else if(     IsObscuration(fStartNode)) fTypeStart = kObs;
    else if(          IsMirror(fStartNode)) fTypeStart = kMirror;
    else if(IsOpticalComponent(fStartNode)) fTypeStart = kOpt;
    else if(    IsFocalSurface(fStartNode)) fTypeStart = kFocus;
    else                                    fTypeStart = kOther;

    // Check type of end node
    if     (                  !fEndNode)  fTypeEnd = kNull;
    else if(            IsLens(fEndNode)) fTypeEnd = kLens;
    else if(     IsObscuration(fEndNode)) fTypeEnd = kObs;
    else if(          IsMirror(fEndNode)) fTypeEnd = kMirror;
    else if(IsOpticalComponent(fEndNode)) fTypeEnd = kOpt;
    else if(    IsFocalSurface(fEndNode)) fTypeEnd = kFocus;
    else                                  fTypeEnd = kOther;

    fStep = GetStep(); // distance to the next boundary
    if(fTypeEnd == kMirror){
      fStep -= kEpsilon; // make sure that the photon do NOT cross the boundary
    } else {
      fStep += kEpsilon; // make sure that the photon crosses the boundary
    } // if

    if(fTypeStart == kLens){
      Double_t abs = ((ALens*)fStartNode->GetVolume())->GetAbsorptionLength(lambda);
      if(abs > 0){
        Double_t abs_step = gRandom->Exp(abs);
        if(abs_step < fStep){
          Double_t n1 = ((ALens*)fStartNode->GetVolume())->GetRefractiveIndex(ray.GetLambda());
          Double_t speed = TMath::C()*m()/n1;
          ray.AddPoint(fX1[0] + fD1[0]*abs_step, fX1[1] + fD1[1]*abs_step, fX1[2] + fD1[2]*abs_step, fX1[3] + abs_step/speed);
          ray.Absorb();
          continue;
        } // if
      } // if
    } // if

    if((fTypeStart == kNull or fTypeStart == kOpt or fTypeStart == kLens or fTypeStart == kOther)
       and fTypeEnd == kMirror){
      Double_t n1 = fTypeStart == kLens ? ((ALens*)fStartNode->GetVolume())->GetRefractiveIndex(ray.GetLambda()) : 1.;
      DoReflection(n1, ray);
    } else if((fTypeStart == kNull or fTypeStart == kOpt or fTypeStart == kOther)
               and fTypeEnd == kLens){
      Double_t n1 = 1; // Assume refractive index equals 1 (= vacuum)
      Double_t n2 = ((ALens*)fEndNode->GetVolume())->GetRefractiveIndex(ray.GetLambda());
      DoFresnel(n1, n2, ray);
    } else if((fTypeStart == kNull or fTypeStart == kLens or fTypeStart == kOpt or fTypeStart == kOther)
               and (fTypeEnd == kObs or fTypeEnd == kFocus)){

      for(Int_t i = 0; i < 3; i++){
        fX2[i] = fX1[i] + fStep*fD1[i];
      } // i
      if (fTypeStart == kLens){
        Double_t n1 = ((ALens*)fStartNode->GetVolume())->GetRefractiveIndex(ray.GetLambda());
        Double_t speed = TMath::C()*m()/n1;
        fX2[3] = fX1[3] + fStep/speed;
      } else {
        Double_t speed = TMath::C()*m();
        fX2[3] = fX1[3] + fStep/speed;
      } // if
      ray.AddPoint(fX2[0], fX2[1], fX2[2], fX2[3]);
    } else if((fTypeStart == kNull or fTypeStart == kOpt or fTypeStart == kOther)
               and (fTypeEnd == kOther or fTypeEnd == kOpt)){

      for(Int_t i = 0; i < 3; i++){
        fX2[i] = fX1[i] + fStep*fD1[i];
      } // i
      Double_t speed = TMath::C()*m();
      fX2[3] = fX1[3] + fStep/speed;
      ray.AddPoint(fX2[0], fX2[1], fX2[2], fX2[3]);
    } else if(fTypeStart == kLens and fTypeEnd == kLens){
      Double_t n1 = ((ALens*)fStartNode->GetVolume())->GetRefractiveIndex(lambda);
      Double_t n2 = ((ALens*)fEndNode->GetVolume())->GetRefractiveIndex(lambda);
      DoFresnel(n1, n2, ray);
    } else if(fTypeStart == kLens and
              (fTypeEnd == kNull or fTypeEnd == kOpt or fTypeEnd == kOther)){
      Double_t n1 = ((ALens*)fStartNode->GetVolume())->GetRefractiveIndex(lambda);
      Double_t n2 = 1; // Assume refractive index equals 1 (= vacuum)
      DoFresnel(n1, n2, ray);
    } // if

    if(fTypeEnd == kNull){
      for(Int_t i = 0; i < 3; i++){
        fX2[i] = fX1[i] + fStep*fD1[i];
      } // i
      Double_t speed = TMath::C()*m();
      fX2[3] = fX1[3] + fStep/speed;
      ray.AddPoint(fX2[0], fX2[1], fX2[2], fX2[3]);
      ray.Exit();
    } else if(fTypeStart == kFocus or fTypeStart == kObs or fTypeStart == kMirror or fTypeEnd == kObs){
      ray.Stop();
    } else if(fTypeEnd == kFocus){
      ray.Focus();
    } // if

    if(ray.IsRunning() and ray.GetNpoints() >= fLimit){
      ray.Suspend();
    } // if

  } // while
}

//_____________________________________________________________________________
void AOpticsManager::TraceNonSequential(ARayArray& array)
{
  TObjArray* running = array.GetRunning();

#ifdef MULTI_THREAD_NAVIGATION
  omp_set_num_threads(fNThreads);
#pragma omp parallel
#pragma omp parallel for
#endif
  for(Int_t i = 0; i <= running->GetLast(); i++){
    ARay* ray = (ARay*)(*running)[i];
    if(!ray) continue;

    ray = (ARay*)running->RemoveAt(i);
    TraceNonSequential(*ray);
    array.Add(ray);
  } // i
}

//_____________________________________________________________________________
void AOpticsManager::SetLimit(Int_t n)
{
  if(n > 0){
    fLimit = n;
  } // if
}
<|endoftext|>