<commit_before>//
//   Copyright 2015 Pixar
//
//   Licensed under the Apache License, Version 2.0 (the "Apache License")
//   with the following modification; you may not use this file except in
//   compliance with the Apache License and the following modification to it:
//   Section 6. Trademarks. is deleted and replaced with:
//
//   6. Trademarks. This License does not grant permission to use the trade
//      names, trademarks, service marks, or product names of the Licensor
//      and its affiliates, except as required to comply with Section 4(c) of
//      the License and to reproduce the content of the NOTICE file.
//
//   You may obtain a copy of the Apache License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the Apache License with the above modification is
//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//   KIND, either express or implied. See the Apache License for the specific
//   language governing permissions and limitations under the Apache License.
//

#include "../osd/glComputeEvaluator.h"

#include <cassert>
#include <sstream>
#include <string>
#include <vector>

#include "../far/error.h"
#include "../far/stencilTable.h"

namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {

namespace Osd {

static const char *shaderSource =
#include "../osd/glslComputeKernel.gen.h"
;

template <class T> GLuint
createSSBO(std::vector<T> const & src) {
    GLuint devicePtr = 0;
    glGenBuffers(1, &devicePtr);

#if defined(GL_EXT_direct_state_access)
    if (glNamedBufferDataEXT) {
        glNamedBufferDataEXT(devicePtr, src.size()*sizeof(T),
                             &src.at(0), GL_STATIC_DRAW);
    } else {
#else
    {
#endif
        GLint prev = 0;
        glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &prev);
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, devicePtr);
        glBufferData(GL_SHADER_STORAGE_BUFFER, src.size()*sizeof(T),
                     &src.at(0), GL_STATIC_DRAW);
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, prev);
    }

    return devicePtr;
}

GLStencilTableSSBO::GLStencilTableSSBO(
    Far::StencilTable const *stencilTable) {
    _numStencils = stencilTable->GetNumStencils();
    if (_numStencils > 0) {
        _sizes   = createSSBO(stencilTable->GetSizes());
        _offsets = createSSBO(stencilTable->GetOffsets());
        _indices = createSSBO(stencilTable->GetControlIndices());
        _weights = createSSBO(stencilTable->GetWeights());
        _duWeights = _dvWeights = 0;
    } else {
        _sizes = _offsets = _indices = _weights = 0;
        _duWeights = _dvWeights = 0;
    }
}

GLStencilTableSSBO::GLStencilTableSSBO(
    Far::LimitStencilTable const *limitStencilTable) {
    _numStencils = limitStencilTable->GetNumStencils();
    if (_numStencils > 0) {
        _sizes   = createSSBO(limitStencilTable->GetSizes());
        _offsets = createSSBO(limitStencilTable->GetOffsets());
        _indices = createSSBO(limitStencilTable->GetControlIndices());
        _weights = createSSBO(limitStencilTable->GetWeights());
        _duWeights = createSSBO(limitStencilTable->GetDuWeights());
        _dvWeights = createSSBO(limitStencilTable->GetDvWeights());
    } else {
        _sizes = _offsets = _indices = _weights = 0;
        _duWeights = _dvWeights = 0;
    }
}

GLStencilTableSSBO::~GLStencilTableSSBO() {
    if (_sizes)   glDeleteBuffers(1, &_sizes);
    if (_offsets) glDeleteBuffers(1, &_offsets);
    if (_indices) glDeleteBuffers(1, &_indices);
    if (_weights) glDeleteBuffers(1, &_weights);
    if (_duWeights) glDeleteBuffers(1, &_duWeights);
    if (_dvWeights) glDeleteBuffers(1, &_dvWeights);
}

// ---------------------------------------------------------------------------

GLComputeEvaluator::GLComputeEvaluator() : _workGroupSize(64) {
    memset (&_stencilKernel, 0, sizeof(_stencilKernel));
    memset (&_patchKernel, 0, sizeof(_patchKernel));
}

GLComputeEvaluator::~GLComputeEvaluator() {
    if (_stencilKernel.program) {
        glDeleteProgram(_stencilKernel.program);
    }
    if (_patchKernel.program) {
        glDeleteProgram(_patchKernel.program);
    }
}

static GLuint
compileKernel(BufferDescriptor const &srcDesc,
              BufferDescriptor const &dstDesc,
              BufferDescriptor const & /* duDesc */,
              BufferDescriptor const & /* dvDesc */,
              const char *kernelDefine,
              int workGroupSize) {
    GLuint program = glCreateProgram();

    GLuint shader = glCreateShader(GL_COMPUTE_SHADER);

    std::ostringstream defines;
    defines << "#define LENGTH "     << srcDesc.length << "\n"
            << "#define SRC_STRIDE " << srcDesc.stride << "\n"
            << "#define DST_STRIDE " << dstDesc.stride << "\n"
            << "#define WORK_GROUP_SIZE " << workGroupSize << "\n"
            << kernelDefine << "\n";
    std::string defineStr = defines.str();

    const char *shaderSources[3] = {"#version 430\n", 0, 0};
    shaderSources[1] = defineStr.c_str();
    shaderSources[2] = shaderSource;
    glShaderSource(shader, 3, shaderSources, NULL);
    glCompileShader(shader);
    glAttachShader(program, shader);

    GLint linked = 0;
    glLinkProgram(program);
    glGetProgramiv(program, GL_LINK_STATUS, &linked);

    if (linked == GL_FALSE) {
        char buffer[1024];
        glGetShaderInfoLog(shader, 1024, NULL, buffer);
        Far::Error(Far::FAR_RUNTIME_ERROR, buffer);

        glGetProgramInfoLog(program, 1024, NULL, buffer);
        Far::Error(Far::FAR_RUNTIME_ERROR, buffer);

        glDeleteProgram(program);
        return 0;
    }

    glDeleteShader(shader);

    return program;
}

bool
GLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
                            BufferDescriptor const &dstDesc,
                            BufferDescriptor const &duDesc,
                            BufferDescriptor const &dvDesc) {

    // create a stencil kernel
    if (!_stencilKernel.Compile(srcDesc, dstDesc, duDesc, dvDesc,
                                _workGroupSize)) {
        return false;
    }

    // create a patch kernel
    if (!_patchKernel.Compile(srcDesc, dstDesc, duDesc, dvDesc,
                              _workGroupSize)) {
        return false;
    }

    return true;
}

/* static */
void
GLComputeEvaluator::Synchronize(void * /*kernel*/) {
    // XXX: this is currently just for the performance measuring purpose.
    // need to be reimplemented by fence and sync.
    glFinish();
}

bool
GLComputeEvaluator::EvalStencils(
    GLuint srcBuffer, BufferDescriptor const &srcDesc,
    GLuint dstBuffer, BufferDescriptor const &dstDesc,
    GLuint duBuffer,  BufferDescriptor const &duDesc,
    GLuint dvBuffer,  BufferDescriptor const &dvDesc,
    GLuint sizesBuffer,
    GLuint offsetsBuffer,
    GLuint indicesBuffer,
    GLuint weightsBuffer,
    GLuint duWeightsBuffer,
    GLuint dvWeightsBuffer,
    int start, int end) const {

    if (!_stencilKernel.program) return false;
    int count = end - start;
    if (count <= 0) {
        return true;
    }

    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, sizesBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, offsetsBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, indicesBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, weightsBuffer);
    if (duWeightsBuffer)
        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, duWeightsBuffer);
    if (dvWeightsBuffer)
        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 9, dvWeightsBuffer);

    glUseProgram(_stencilKernel.program);

    glUniform1i(_stencilKernel.uniformStart,     start);
    glUniform1i(_stencilKernel.uniformEnd,       end);
    glUniform1i(_stencilKernel.uniformSrcOffset, srcDesc.offset);
    glUniform1i(_stencilKernel.uniformDstOffset, dstDesc.offset);
    if (_stencilKernel.uniformDuDesc > 0) {
        glUniform3i(_stencilKernel.uniformDuDesc,
                    duDesc.offset, duDesc.length, duDesc.stride);
    }
    if (_stencilKernel.uniformDvDesc > 0) {
        glUniform3i(_stencilKernel.uniformDvDesc,
                    dvDesc.offset, dvDesc.length, dvDesc.stride);
    }

    glDispatchCompute((count + _workGroupSize - 1) / _workGroupSize, 1, 1);

    glUseProgram(0);

    glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
    for (int i = 0; i < 10; ++i) {
        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, 0);
    }

    return true;
}

bool
GLComputeEvaluator::EvalPatches(
    GLuint srcBuffer, BufferDescriptor const &srcDesc,
    GLuint dstBuffer, BufferDescriptor const &dstDesc,
    GLuint duBuffer,  BufferDescriptor const &duDesc,
    GLuint dvBuffer,  BufferDescriptor const &dvDesc,
    int numPatchCoords,
    GLuint patchCoordsBuffer,
    const PatchArrayVector &patchArrays,
    GLuint patchIndexBuffer,
    GLuint patchParamsBuffer) const {

    if (!_patchKernel.program) return false;

    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, patchCoordsBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, patchIndexBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, patchParamsBuffer);

    glUseProgram(_patchKernel.program);

    glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset);
    glUniform1i(_patchKernel.uniformDstOffset, dstDesc.offset);
    glUniform4iv(_patchKernel.uniformPatchArray, (int)patchArrays.size(),
                 (const GLint*)&patchArrays[0]);
    glUniform3i(_patchKernel.uniformDuDesc, duDesc.offset, duDesc.length, duDesc.stride);
    glUniform3i(_patchKernel.uniformDvDesc, dvDesc.offset, dvDesc.length, dvDesc.stride);

    glDispatchCompute((numPatchCoords + _workGroupSize - 1) / _workGroupSize, 1, 1);

    glUseProgram(0);

    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, 0);

    return true;
}
// ---------------------------------------------------------------------------

GLComputeEvaluator::_StencilKernel::_StencilKernel() : program(0) {
}
GLComputeEvaluator::_StencilKernel::~_StencilKernel() {
    if (program) {
        glDeleteProgram(program);
    }
}

bool
GLComputeEvaluator::_StencilKernel::Compile(BufferDescriptor const &srcDesc,
                                            BufferDescriptor const &dstDesc,
                                            BufferDescriptor const &duDesc,
                                            BufferDescriptor const &dvDesc,
                                            int workGroupSize) {
    // create stencil kernel
    if (program) {
        glDeleteProgram(program);
    }

    bool derivatives = (duDesc.length > 0 || dvDesc.length > 0);
    const char *kernelDef = derivatives
        ? "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS\n"
          "#define OPENSUBDIV_GLSL_COMPUTE_USE_DERIVATIVES\n"
        : "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS\n";

    if (program) {
        glDeleteProgram(program);
    }
    program = compileKernel(srcDesc, dstDesc, duDesc, dvDesc, kernelDef,
                            workGroupSize);
    if (program == 0) return false;

    // cache uniform locations (TODO: use uniform block)
    uniformStart     = glGetUniformLocation(program, "batchStart");
    uniformEnd       = glGetUniformLocation(program, "batchEnd");
    uniformSrcOffset = glGetUniformLocation(program, "srcOffset");
    uniformDstOffset = glGetUniformLocation(program, "dstOffset");
    uniformDuDesc    = glGetUniformLocation(program, "duDesc");
    uniformDvDesc    = glGetUniformLocation(program, "dvDesc");

    return true;
}

// ---------------------------------------------------------------------------

GLComputeEvaluator::_PatchKernel::_PatchKernel() : program(0) {
}
GLComputeEvaluator::_PatchKernel::~_PatchKernel() {
    if (program) {
        glDeleteProgram(program);
    }
}

bool
GLComputeEvaluator::_PatchKernel::Compile(BufferDescriptor const &srcDesc,
                                          BufferDescriptor const &dstDesc,
                                          BufferDescriptor const &duDesc,
                                          BufferDescriptor const &dvDesc,
                                          int workGroupSize) {
    // create stencil kernel
    if (program) {
        glDeleteProgram(program);
    }

    bool derivatives = (duDesc.length > 0 || dvDesc.length > 0);
    const char *kernelDef = derivatives
        ? "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES\n"
          "#define OPENSUBDIV_GLSL_COMPUTE_USE_DERIVATIVES\n"
        : "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES\n";

    if (program) {
        glDeleteProgram(program);
    }
    program = compileKernel(srcDesc, dstDesc, duDesc, dvDesc, kernelDef,
                            workGroupSize);
    if (program == 0) return false;

    // cache uniform locations
    uniformSrcOffset  = glGetUniformLocation(program, "srcOffset");
    uniformDstOffset  = glGetUniformLocation(program, "dstOffset");
    uniformPatchArray = glGetUniformLocation(program, "patchArray");
    uniformDuDesc     = glGetUniformLocation(program, "duDesc");
    uniformDvDesc     = glGetUniformLocation(program, "dvDesc");

    return true;
}

}  // end namespace Osd

}  // end namespace OPENSUBDIV_VERSION
}  // end namespace OpenSubdiv
<commit_msg>Fix GLSL program being deleted twice in GLSL Compute controller<commit_after>//
//   Copyright 2015 Pixar
//
//   Licensed under the Apache License, Version 2.0 (the "Apache License")
//   with the following modification; you may not use this file except in
//   compliance with the Apache License and the following modification to it:
//   Section 6. Trademarks. is deleted and replaced with:
//
//   6. Trademarks. This License does not grant permission to use the trade
//      names, trademarks, service marks, or product names of the Licensor
//      and its affiliates, except as required to comply with Section 4(c) of
//      the License and to reproduce the content of the NOTICE file.
//
//   You may obtain a copy of the Apache License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the Apache License with the above modification is
//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//   KIND, either express or implied. See the Apache License for the specific
//   language governing permissions and limitations under the Apache License.
//

#include "../osd/glComputeEvaluator.h"

#include <cassert>
#include <sstream>
#include <string>
#include <vector>

#include "../far/error.h"
#include "../far/stencilTable.h"

namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {

namespace Osd {

static const char *shaderSource =
#include "../osd/glslComputeKernel.gen.h"
;

template <class T> GLuint
createSSBO(std::vector<T> const & src) {
    GLuint devicePtr = 0;
    glGenBuffers(1, &devicePtr);

#if defined(GL_EXT_direct_state_access)
    if (glNamedBufferDataEXT) {
        glNamedBufferDataEXT(devicePtr, src.size()*sizeof(T),
                             &src.at(0), GL_STATIC_DRAW);
    } else {
#else
    {
#endif
        GLint prev = 0;
        glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &prev);
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, devicePtr);
        glBufferData(GL_SHADER_STORAGE_BUFFER, src.size()*sizeof(T),
                     &src.at(0), GL_STATIC_DRAW);
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, prev);
    }

    return devicePtr;
}

GLStencilTableSSBO::GLStencilTableSSBO(
    Far::StencilTable const *stencilTable) {
    _numStencils = stencilTable->GetNumStencils();
    if (_numStencils > 0) {
        _sizes   = createSSBO(stencilTable->GetSizes());
        _offsets = createSSBO(stencilTable->GetOffsets());
        _indices = createSSBO(stencilTable->GetControlIndices());
        _weights = createSSBO(stencilTable->GetWeights());
        _duWeights = _dvWeights = 0;
    } else {
        _sizes = _offsets = _indices = _weights = 0;
        _duWeights = _dvWeights = 0;
    }
}

GLStencilTableSSBO::GLStencilTableSSBO(
    Far::LimitStencilTable const *limitStencilTable) {
    _numStencils = limitStencilTable->GetNumStencils();
    if (_numStencils > 0) {
        _sizes   = createSSBO(limitStencilTable->GetSizes());
        _offsets = createSSBO(limitStencilTable->GetOffsets());
        _indices = createSSBO(limitStencilTable->GetControlIndices());
        _weights = createSSBO(limitStencilTable->GetWeights());
        _duWeights = createSSBO(limitStencilTable->GetDuWeights());
        _dvWeights = createSSBO(limitStencilTable->GetDvWeights());
    } else {
        _sizes = _offsets = _indices = _weights = 0;
        _duWeights = _dvWeights = 0;
    }
}

GLStencilTableSSBO::~GLStencilTableSSBO() {
    if (_sizes)   glDeleteBuffers(1, &_sizes);
    if (_offsets) glDeleteBuffers(1, &_offsets);
    if (_indices) glDeleteBuffers(1, &_indices);
    if (_weights) glDeleteBuffers(1, &_weights);
    if (_duWeights) glDeleteBuffers(1, &_duWeights);
    if (_dvWeights) glDeleteBuffers(1, &_dvWeights);
}

// ---------------------------------------------------------------------------

GLComputeEvaluator::GLComputeEvaluator() : _workGroupSize(64) {
    memset (&_stencilKernel, 0, sizeof(_stencilKernel));
    memset (&_patchKernel, 0, sizeof(_patchKernel));
}

GLComputeEvaluator::~GLComputeEvaluator() {
}

static GLuint
compileKernel(BufferDescriptor const &srcDesc,
              BufferDescriptor const &dstDesc,
              BufferDescriptor const & /* duDesc */,
              BufferDescriptor const & /* dvDesc */,
              const char *kernelDefine,
              int workGroupSize) {
    GLuint program = glCreateProgram();

    GLuint shader = glCreateShader(GL_COMPUTE_SHADER);

    std::ostringstream defines;
    defines << "#define LENGTH "     << srcDesc.length << "\n"
            << "#define SRC_STRIDE " << srcDesc.stride << "\n"
            << "#define DST_STRIDE " << dstDesc.stride << "\n"
            << "#define WORK_GROUP_SIZE " << workGroupSize << "\n"
            << kernelDefine << "\n";
    std::string defineStr = defines.str();

    const char *shaderSources[3] = {"#version 430\n", 0, 0};
    shaderSources[1] = defineStr.c_str();
    shaderSources[2] = shaderSource;
    glShaderSource(shader, 3, shaderSources, NULL);
    glCompileShader(shader);
    glAttachShader(program, shader);

    GLint linked = 0;
    glLinkProgram(program);
    glGetProgramiv(program, GL_LINK_STATUS, &linked);

    if (linked == GL_FALSE) {
        char buffer[1024];
        glGetShaderInfoLog(shader, 1024, NULL, buffer);
        Far::Error(Far::FAR_RUNTIME_ERROR, buffer);

        glGetProgramInfoLog(program, 1024, NULL, buffer);
        Far::Error(Far::FAR_RUNTIME_ERROR, buffer);

        glDeleteProgram(program);
        return 0;
    }

    glDeleteShader(shader);

    return program;
}

bool
GLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
                            BufferDescriptor const &dstDesc,
                            BufferDescriptor const &duDesc,
                            BufferDescriptor const &dvDesc) {

    // create a stencil kernel
    if (!_stencilKernel.Compile(srcDesc, dstDesc, duDesc, dvDesc,
                                _workGroupSize)) {
        return false;
    }

    // create a patch kernel
    if (!_patchKernel.Compile(srcDesc, dstDesc, duDesc, dvDesc,
                              _workGroupSize)) {
        return false;
    }

    return true;
}

/* static */
void
GLComputeEvaluator::Synchronize(void * /*kernel*/) {
    // XXX: this is currently just for the performance measuring purpose.
    // need to be reimplemented by fence and sync.
    glFinish();
}

bool
GLComputeEvaluator::EvalStencils(
    GLuint srcBuffer, BufferDescriptor const &srcDesc,
    GLuint dstBuffer, BufferDescriptor const &dstDesc,
    GLuint duBuffer,  BufferDescriptor const &duDesc,
    GLuint dvBuffer,  BufferDescriptor const &dvDesc,
    GLuint sizesBuffer,
    GLuint offsetsBuffer,
    GLuint indicesBuffer,
    GLuint weightsBuffer,
    GLuint duWeightsBuffer,
    GLuint dvWeightsBuffer,
    int start, int end) const {

    if (!_stencilKernel.program) return false;
    int count = end - start;
    if (count <= 0) {
        return true;
    }

    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, sizesBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, offsetsBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, indicesBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, weightsBuffer);
    if (duWeightsBuffer)
        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, duWeightsBuffer);
    if (dvWeightsBuffer)
        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 9, dvWeightsBuffer);

    glUseProgram(_stencilKernel.program);

    glUniform1i(_stencilKernel.uniformStart,     start);
    glUniform1i(_stencilKernel.uniformEnd,       end);
    glUniform1i(_stencilKernel.uniformSrcOffset, srcDesc.offset);
    glUniform1i(_stencilKernel.uniformDstOffset, dstDesc.offset);
    if (_stencilKernel.uniformDuDesc > 0) {
        glUniform3i(_stencilKernel.uniformDuDesc,
                    duDesc.offset, duDesc.length, duDesc.stride);
    }
    if (_stencilKernel.uniformDvDesc > 0) {
        glUniform3i(_stencilKernel.uniformDvDesc,
                    dvDesc.offset, dvDesc.length, dvDesc.stride);
    }

    glDispatchCompute((count + _workGroupSize - 1) / _workGroupSize, 1, 1);

    glUseProgram(0);

    glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
    for (int i = 0; i < 10; ++i) {
        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, 0);
    }

    return true;
}

bool
GLComputeEvaluator::EvalPatches(
    GLuint srcBuffer, BufferDescriptor const &srcDesc,
    GLuint dstBuffer, BufferDescriptor const &dstDesc,
    GLuint duBuffer,  BufferDescriptor const &duDesc,
    GLuint dvBuffer,  BufferDescriptor const &dvDesc,
    int numPatchCoords,
    GLuint patchCoordsBuffer,
    const PatchArrayVector &patchArrays,
    GLuint patchIndexBuffer,
    GLuint patchParamsBuffer) const {

    if (!_patchKernel.program) return false;

    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, patchCoordsBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, patchIndexBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, patchParamsBuffer);

    glUseProgram(_patchKernel.program);

    glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset);
    glUniform1i(_patchKernel.uniformDstOffset, dstDesc.offset);
    glUniform4iv(_patchKernel.uniformPatchArray, (int)patchArrays.size(),
                 (const GLint*)&patchArrays[0]);
    glUniform3i(_patchKernel.uniformDuDesc, duDesc.offset, duDesc.length, duDesc.stride);
    glUniform3i(_patchKernel.uniformDvDesc, dvDesc.offset, dvDesc.length, dvDesc.stride);

    glDispatchCompute((numPatchCoords + _workGroupSize - 1) / _workGroupSize, 1, 1);

    glUseProgram(0);

    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, 0);

    return true;
}
// ---------------------------------------------------------------------------

GLComputeEvaluator::_StencilKernel::_StencilKernel() : program(0) {
}
GLComputeEvaluator::_StencilKernel::~_StencilKernel() {
    if (program) {
        glDeleteProgram(program);
    }
}

bool
GLComputeEvaluator::_StencilKernel::Compile(BufferDescriptor const &srcDesc,
                                            BufferDescriptor const &dstDesc,
                                            BufferDescriptor const &duDesc,
                                            BufferDescriptor const &dvDesc,
                                            int workGroupSize) {
    // create stencil kernel
    if (program) {
        glDeleteProgram(program);
    }

    bool derivatives = (duDesc.length > 0 || dvDesc.length > 0);
    const char *kernelDef = derivatives
        ? "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS\n"
          "#define OPENSUBDIV_GLSL_COMPUTE_USE_DERIVATIVES\n"
        : "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS\n";

    if (program) {
        glDeleteProgram(program);
    }
    program = compileKernel(srcDesc, dstDesc, duDesc, dvDesc, kernelDef,
                            workGroupSize);
    if (program == 0) return false;

    // cache uniform locations (TODO: use uniform block)
    uniformStart     = glGetUniformLocation(program, "batchStart");
    uniformEnd       = glGetUniformLocation(program, "batchEnd");
    uniformSrcOffset = glGetUniformLocation(program, "srcOffset");
    uniformDstOffset = glGetUniformLocation(program, "dstOffset");
    uniformDuDesc    = glGetUniformLocation(program, "duDesc");
    uniformDvDesc    = glGetUniformLocation(program, "dvDesc");

    return true;
}

// ---------------------------------------------------------------------------

GLComputeEvaluator::_PatchKernel::_PatchKernel() : program(0) {
}
GLComputeEvaluator::_PatchKernel::~_PatchKernel() {
    if (program) {
        glDeleteProgram(program);
    }
}

bool
GLComputeEvaluator::_PatchKernel::Compile(BufferDescriptor const &srcDesc,
                                          BufferDescriptor const &dstDesc,
                                          BufferDescriptor const &duDesc,
                                          BufferDescriptor const &dvDesc,
                                          int workGroupSize) {
    // create stencil kernel
    if (program) {
        glDeleteProgram(program);
    }

    bool derivatives = (duDesc.length > 0 || dvDesc.length > 0);
    const char *kernelDef = derivatives
        ? "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES\n"
          "#define OPENSUBDIV_GLSL_COMPUTE_USE_DERIVATIVES\n"
        : "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES\n";

    if (program) {
        glDeleteProgram(program);
    }
    program = compileKernel(srcDesc, dstDesc, duDesc, dvDesc, kernelDef,
                            workGroupSize);
    if (program == 0) return false;

    // cache uniform locations
    uniformSrcOffset  = glGetUniformLocation(program, "srcOffset");
    uniformDstOffset  = glGetUniformLocation(program, "dstOffset");
    uniformPatchArray = glGetUniformLocation(program, "patchArray");
    uniformDuDesc     = glGetUniformLocation(program, "duDesc");
    uniformDvDesc     = glGetUniformLocation(program, "dvDesc");

    return true;
}

}  // end namespace Osd

}  // end namespace OPENSUBDIV_VERSION
}  // end namespace OpenSubdiv
<|endoftext|>


<commit_before>#pragma once

#include <MY_Game.h>

#include <MY_ResourceManager.h>

#include <MY_Scene_Menu.h>
#include <MY_Scene_Box2D.h>
#include <MY_Scene_Bullet3D.h>
#include <MY_Scene_SurfaceShaders.h>
#include <MY_Scene_ScreenShaders.h>
#include <MY_Scene_VR.h>

MY_Game::MY_Game() :
	Game("menu", new MY_Scene_Menu(this), true) // initialize our game with a menu scene
{
	// initialize all of our scenes in the game's scene map for later use
	// only the current scene is updated/rendered by default, so these shouldn't affect performance
	// however, they will be created at the same time as the game, so any load times associated with
	// their creation will be front-loaded. To avoid this, you can check to see if a scene exists immediately
	// before switching to it, and create it then if needed.
	scenes["box2d"] = new MY_Scene_Box2D(this);
	scenes["bullet3d"] = new MY_Scene_Bullet3D(this);
	scenes["surfaceshaders"] = new MY_Scene_SurfaceShaders(this);
	scenes["screenshaders"] = new MY_Scene_ScreenShaders(this);
	scenes["surfaceshaders"] = new MY_Scene_SurfaceShaders(this);
	scenes["vr"] = new MY_Scene_VR(this);
}

MY_Game::~MY_Game(){}

void MY_Game::addSplashes(){
	// add default splashes
	Game::addSplashes();

	// add custom splashes
	addSplash(new Scene_Splash(this, MY_ResourceManager::globalAssets->getTexture("DEFAULT")->texture, MY_ResourceManager::globalAssets->getAudio("DEFAULT")->sound));
}<commit_msg>removed duplicate scene<commit_after>#pragma once

#include <MY_Game.h>

#include <MY_ResourceManager.h>

#include <MY_Scene_Menu.h>
#include <MY_Scene_Box2D.h>
#include <MY_Scene_Bullet3D.h>
#include <MY_Scene_SurfaceShaders.h>
#include <MY_Scene_ScreenShaders.h>
#include <MY_Scene_VR.h>

MY_Game::MY_Game() :
	Game("menu", new MY_Scene_Menu(this), true) // initialize our game with a menu scene
{
	// initialize all of our scenes in the game's scene map for later use
	// only the current scene is updated/rendered by default, so these shouldn't affect performance
	// however, they will be created at the same time as the game, so any load times associated with
	// their creation will be front-loaded. To avoid this, you can check to see if a scene exists immediately
	// before switching to it, and create it then if needed.
	scenes["box2d"] = new MY_Scene_Box2D(this);
	scenes["bullet3d"] = new MY_Scene_Bullet3D(this);
	scenes["screenshaders"] = new MY_Scene_ScreenShaders(this);
	scenes["surfaceshaders"] = new MY_Scene_SurfaceShaders(this);
	scenes["vr"] = new MY_Scene_VR(this);
}

MY_Game::~MY_Game(){}

void MY_Game::addSplashes(){
	// add default splashes
	Game::addSplashes();

	// add custom splashes
	addSplash(new Scene_Splash(this, MY_ResourceManager::globalAssets->getTexture("DEFAULT")->texture, MY_ResourceManager::globalAssets->getAudio("DEFAULT")->sound));
}<|endoftext|>


<commit_before>
#include "units/enemy-unit.h"

#include "engine/game.h"

void EnemyUnit::Load() {
  sprite_.set_texture(Game::GetResourcesManager()->Enemy());
  set_movement_speed(50.f);
  set_rotation(180);
}

void EnemyUnit::Attack() {
  life_--;
  cout << "life_" << life_ << endl;
  if (life_ == 0) {
    cout << "Atacando" << endl;
    Remove_(ENEMY_DIED);
    return;
  }
}

void EnemyUnit::Remove_(GameEventType type) {
  auto events = Game::GetEventsManager();
  events->Trigger(GameEvent(type));
  auto instances = Game::GetInstancesManager();
  instances->MarkToRemoveAndDelete(this);
  auto map_controller = Game::GetMapController();
  map_controller->RemoveEnemy(this);
}

void EnemyUnit::Step(sf::Time elapsed) {
  Unit::Step(elapsed);

  auto map_controller = Game::GetMapController();
  Vec2u tile(map_controller->CalcRowCol(position()));
  map_controller->PlaceEnemy(tile, this);

  if (map_controller->ReachedCastle(tile)) {
    Remove_(ENEMY_REACHED_CASTLE);
    return;
  }
}
<commit_msg>Remove debug couts.<commit_after>
#include "units/enemy-unit.h"

#include "engine/game.h"

void EnemyUnit::Load() {
  sprite_.set_texture(Game::GetResourcesManager()->Enemy());
  set_movement_speed(50.f);
  set_rotation(180);
}

void EnemyUnit::Attack() {
  life_--;
  if (life_ == 0) {
    Remove_(ENEMY_DIED);
    return;
  }
}

void EnemyUnit::Remove_(GameEventType type) {
  auto events = Game::GetEventsManager();
  events->Trigger(GameEvent(type));
  auto instances = Game::GetInstancesManager();
  instances->MarkToRemoveAndDelete(this);
  auto map_controller = Game::GetMapController();
  map_controller->RemoveEnemy(this);
}

void EnemyUnit::Step(sf::Time elapsed) {
  Unit::Step(elapsed);

  auto map_controller = Game::GetMapController();
  Vec2u tile(map_controller->CalcRowCol(position()));
  map_controller->PlaceEnemy(tile, this);

  if (map_controller->ReachedCastle(tile)) {
    Remove_(ENEMY_REACHED_CASTLE);
    return;
  }
}
<|endoftext|>


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

#include "MainView.h"
#include "../Scene.h"
#include "../cursor/Cursor.h"
#include "../items/Item.h"
#include "../VisualizationBasePlugin.h"

#include "Logger/src/Timer.h"
#include "Logger/src/Log.h"

namespace Visualization {

MainView::MainView(Scene *scene) :
	View(scene, nullptr), miniMap{new MiniMap{scene, this}}, scaleLevel{SCALING_FACTOR}
{
	setRenderHint(QPainter::Antialiasing);
	setRenderHint(QPainter::TextAntialiasing);

	setTransformationAnchor(QGraphicsView::AnchorUnderMouse);

	setMiniMapSize(MINIMAP_DEFAULT_WIDTH, MINIMAP_DEFAULT_HEIGHT);
}

MainView::~MainView()
{
	SAFE_DELETE(miniMap);
}

void MainView::setMiniMapSize(int width, int height)
{
	if ( miniMap )
	{
		miniMap->resize(width, height);
		miniMap->sceneRectChanged(scene()->sceneRect());
	}
}

bool MainView::event( QEvent *event )
{
	bool result = false;

	switch (event->type())
	{
		case QEvent::KeyPress :
		{
			QKeyEvent *k = (QKeyEvent *)event;
			keyPressEvent(k);
			if (k->key() == Qt::Key_Backtab || k->key() == Qt::Key_Tab ) event->accept();
			result = true;
		}
		break;
		case QEvent::KeyRelease :
		{
			QKeyEvent *k = (QKeyEvent *)event;
			keyReleaseEvent(k);
			if (k->key() == Qt::Key_Backtab || k->key() == Qt::Key_Tab ) event->accept();
			result = true;
		}
		break;
		default: result = View::event( event );
		break;
	}

	// The checks below are necessary to avoid infinite recursion.
	if ( event->type() != QEvent::ChildAdded
			&& event->type() != QEvent::ChildRemoved
			&& event->type() != QEvent::ChildPolished) updateInfoLabels();
	return result;
}

void MainView::resizeEvent(QResizeEvent *event)
{
	View::resizeEvent(event);
	if ( miniMap )
	{
		miniMap->updatePosition();
		miniMap->visibleRectChanged();
	}
}

void MainView::wheelEvent(QWheelEvent *event)
{
	// Zoom
	if (event->modifiers() == Qt::ControlModifier)
	{
		if ( event->delta() > 0 ) scaleLevel--;
		else scaleLevel++;

		if ( scaleLevel <= 0 ) scaleLevel = 1;
		qreal factor = scaleFactor();
		setTransform(QTransform::fromScale(factor, factor));

		if ( miniMap ) miniMap->visibleRectChanged();

		scene()->setMainViewScalingFactor(factor);
	}
	// Scroll
	else if (event->modifiers() == Qt::NoModifier || event->modifiers() == Qt::ShiftModifier)
	{
		auto bar = event->orientation() == Qt::Vertical && event->modifiers() == Qt::NoModifier
				? verticalScrollBar() : horizontalScrollBar();

		bar->setValue( bar->value() - event->delta() );
	}
	else
		View::wheelEvent(event);
}

qreal MainView::scaleFactor() const
{
	if (scaleLevel < SCALING_FACTOR)
		return SCALING_FACTOR / (qreal) scaleLevel;
	else return std::pow(2, SCALING_FACTOR - scaleLevel);
}

void MainView::scrollContentsBy(int dx, int dy)
{
	View::scrollContentsBy(dx, dy);
	if ( miniMap ) miniMap->visibleRectChanged();
}

void MainView::keyPressEvent(QKeyEvent *event)
{
	if ( (event->modifiers() & Qt::ControlModifier || event->modifiers() & Qt::ShiftModifier)
			&& event->key() == Qt::Key_Print)
	{
		event->accept();
		scene()->setHiddenItemCategories(0);

		QPrinter printer;
		printer.setOutputFormat(QPrinter::PdfFormat);
		printer.setFullPage(true);
		printer.setResolution(300);

		QSvgGenerator svggen;
		svggen.setResolution(90);

		bool ownerIgnoresScale = setCursorAndOwnerIgnoreScaleForScreenShot(false, false);

		if (event->modifiers() & Qt::ShiftModifier)
		{
			// Print scene
			VisualizationBasePlugin::log().info("Capturing a screenshot of the entire scene.");

			printer.setOutputFileName("screenshot-scene.pdf");
			printer.setPaperSize(scene()->sceneRect().size().toSize(), QPrinter::Point);
			QPainter painter{&printer};
			painter.setRenderHint(QPainter::Antialiasing);
			scene()->render( &painter );

			svggen.setFileName("screenshot-scene.svg");
			svggen.setSize(scene()->sceneRect().size().toSize());
			QPainter svgPainter{&svggen};
			svgPainter.setRenderHint(QPainter::Antialiasing);
			scene()->render(&svgPainter);

			QImage image{PNG_SCREENSHOT_SCALE * scene()->sceneRect().size().toSize(), QImage::Format_ARGB32};
			image.fill(Qt::transparent);
			QPainter pmapPainter{&image};
			pmapPainter.setRenderHint(QPainter::Antialiasing);
			//pmapPainter.scale(2, 2);
			scene()->render(&pmapPainter);
			image.save("screenshot-scene.png");
		}
		else
		{
			// Print view
			VisualizationBasePlugin::log().info("Capturing a screenshot of the current view.");

			printer.setOutputFileName("screenshot-view.pdf");
			printer.setPaperSize(viewport()->rect().size(), QPrinter::Point);
			QPainter painter{&printer};
			painter.setRenderHint(QPainter::Antialiasing);
			render(&painter);

			svggen.setFileName("screenshot-view.svg");
			svggen.setSize(viewport()->rect().size());
			QPainter svgPainter{&svggen};
			svgPainter.setRenderHint(QPainter::Antialiasing);
			render(&svgPainter);

			QImage image{PNG_SCREENSHOT_SCALE * viewport()->rect().size(), QImage::Format_ARGB32};
			image.fill(Qt::transparent);
			QPainter pmapPainter{&image};
			pmapPainter.setRenderHint(QPainter::Antialiasing);
			render(&pmapPainter);
			image.save("screenshot-view.png");
		}

		setCursorAndOwnerIgnoreScaleForScreenShot(true, ownerIgnoresScale);
	}
	else if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier) && event->key() == Qt::Key_P)
	{
		// Toggle presentation mode (full screen + no scroll bars + no minimap)

		event->accept();
		QWidget* window = this;
		while (window->parentWidget()) window = window->parentWidget();

		if (window->isFullScreen())
		{
			window->showNormal();
			setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
			setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
			miniMap->show();
		}
		else
		{
			window->showFullScreen();
			setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
			setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
			miniMap->hide();
		}
	}
	else if (event->modifiers() == Qt::NoModifier && event->key() == Qt::Key_F11)
	{
		// Toggle fullscreen only
		event->accept();
		QWidget* window = this;
		while (window->parentWidget()) window = window->parentWidget();

		if (window->isFullScreen()) window->showNormal();
		else window->showFullScreen();
	}
	else if (event->modifiers() == Qt::NoModifier && event->key() == Qt::Key_F10)
	{
		event->accept();
		if (miniMap->width() == MINIMAP_DEFAULT_WIDTH && miniMap->height() ==  MINIMAP_DEFAULT_HEIGHT)
			setMiniMapSize(width(), height());
		else setMiniMapSize(MINIMAP_DEFAULT_WIDTH, MINIMAP_DEFAULT_HEIGHT);
	}
	else if (event->modifiers() == Qt::NoModifier && event->key() == Qt::Key_F9)
	{
		event->accept();
		if (miniMap->isVisible()) miniMap->hide();
		else miniMap->show();
	}
	else if (event->modifiers() == Qt::NoModifier && event->key() == Qt::Key_F7)
	{
		event->accept();
		showTimers_ = ~showTimers_;
		updateInfoLabels();
	}
	else View::keyPressEvent(event);
}

void MainView::updateInfoLabels()
{
	if (!showTimers_)
	{
		if (!infoLabels_.isEmpty())
		{
			for (auto label : infoLabels_) SAFE_DELETE(label);
			infoLabels_.clear();
		}
		return;
	}

	int labelIndex = 0;
	int yPos = 10;

	// Add timers
	for (auto name : Logger::Timer::timerNames())
	{
		QLabel* label{};

		if (infoLabels_.size() <= labelIndex)
		{
			label = new QLabel{this};
			label->setAttribute(Qt::WA_TransparentForMouseEvents);
			infoLabels_.append(label);
			label->show();
			label->setStyleSheet("QLabel { color : red; }");
		}
		else label = infoLabels_.at(labelIndex);

		// Set the position of the label
		label->move(10, yPos);

		// Construct label text
		auto info = name + ":  ";
		for (auto val : Logger::Timer::timer(name)->values())
			info += QString::number(val) + "  ";

		label->setText(info);
		label->adjustSize();

		++labelIndex;
		yPos+=label->height();
	}

	// Remove unnecessary labels
	while (labelIndex < infoLabels_.size() )
	{
		SAFE_DELETE(infoLabels_.last());
		infoLabels_.removeLast();
	}
}

void MainView::paintEvent(QPaintEvent* event)
{
	auto t = Logger::Timer::start("Main view paint");
	View::paintEvent(event);
	t->tick();
}

void MainView::mouseMoveEvent(QMouseEvent *event)
{
	if (!isPanning_) return View::mouseMoveEvent(event);

	event->accept();
	horizontalScrollBar()->setValue(horizontalScrollBar()->value() - (event->x() - panStartPos_.x()));
	verticalScrollBar()->setValue(verticalScrollBar()->value() - (event->y() - panStartPos_.y()));
	panStartPos_ = event->pos();
}

void MainView::mousePressEvent(QMouseEvent *event)
{
	if (event->modifiers() != Qt::ControlModifier) return View::mousePressEvent(event);

	event->accept();
	isPanning_ = true;
	panStartPos_ = event->pos();
	setCursor(Qt::ClosedHandCursor);
}

void MainView::mouseReleaseEvent(QMouseEvent *event)
{
	if (!isPanning_) return View::mouseReleaseEvent(event);

	event->accept();
	setCursor(Qt::ArrowCursor);
	isPanning_ = false;
}

bool MainView::setCursorAndOwnerIgnoreScaleForScreenShot(bool ignore, bool modifyOwner)
{
	bool ownerIgnoresScale = false;

	auto cursor = scene()->mainCursor();
	if (cursor)
	{
		if ( auto vis = cursor->visualization() ) vis->setFlag(Item::ItemIgnoresTransformations, ignore);
		auto owner = cursor->owner();
		if (owner)
		{
			while (owner->parent()) owner = owner->parent();
			if (!ignore)
			{
				ownerIgnoresScale = owner->flags() & Item::ItemIgnoresTransformations;
				if (ownerIgnoresScale) owner->setFlag(Item::ItemIgnoresTransformations, false);
			}
			else if (modifyOwner) owner->setFlag(Item::ItemIgnoresTransformations, true);
		}
	}

	return ownerIgnoresScale;
}

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

#include "MainView.h"
#include "../Scene.h"
#include "../cursor/Cursor.h"
#include "../items/Item.h"
#include "../VisualizationBasePlugin.h"

#include "Logger/src/Timer.h"
#include "Logger/src/Log.h"

namespace Visualization {

MainView::MainView(Scene *scene) :
	View(scene, nullptr), miniMap{new MiniMap{scene, this}}, scaleLevel{SCALING_FACTOR}
{
	setRenderHint(QPainter::Antialiasing);
	setRenderHint(QPainter::TextAntialiasing);

	setTransformationAnchor(QGraphicsView::AnchorUnderMouse);

	setMiniMapSize(MINIMAP_DEFAULT_WIDTH, MINIMAP_DEFAULT_HEIGHT);
}

MainView::~MainView()
{
	SAFE_DELETE(miniMap);
}

void MainView::setMiniMapSize(int width, int height)
{
	if ( miniMap )
	{
		miniMap->resize(width, height);
		miniMap->sceneRectChanged(scene()->sceneRect());
	}
}

bool MainView::event( QEvent *event )
{
	bool result = false;

	switch (event->type())
	{
		case QEvent::KeyPress :
		{
			QKeyEvent *k = (QKeyEvent *)event;
			keyPressEvent(k);
			if (k->key() == Qt::Key_Backtab || k->key() == Qt::Key_Tab ) event->accept();
			result = true;
		}
		break;
		case QEvent::KeyRelease :
		{
			QKeyEvent *k = (QKeyEvent *)event;
			keyReleaseEvent(k);
			if (k->key() == Qt::Key_Backtab || k->key() == Qt::Key_Tab ) event->accept();
			result = true;
		}
		break;
		default: result = View::event( event );
		break;
	}

	// The checks below are necessary to avoid infinite recursion.
	if ( event->type() != QEvent::ChildAdded
			&& event->type() != QEvent::ChildRemoved
			&& event->type() != QEvent::ChildPolished) updateInfoLabels();
	return result;
}

void MainView::resizeEvent(QResizeEvent *event)
{
	View::resizeEvent(event);
	if ( miniMap )
	{
		miniMap->updatePosition();
		miniMap->visibleRectChanged();
	}
}

void MainView::wheelEvent(QWheelEvent *event)
{
	// Zoom
	if (event->modifiers() == Qt::ControlModifier)
	{
		if ( event->delta() > 0 ) scaleLevel--;
		else scaleLevel++;

		if ( scaleLevel <= 0 ) scaleLevel = 1;
		qreal factor = scaleFactor();
		setTransform(QTransform::fromScale(factor, factor));

		if ( miniMap ) miniMap->visibleRectChanged();

		scene()->setMainViewScalingFactor(factor);
	}
	// Scroll
	else if (event->modifiers() == Qt::NoModifier || event->modifiers() == Qt::ShiftModifier)
	{
		auto bar = event->orientation() == Qt::Vertical && event->modifiers() == Qt::NoModifier
				? verticalScrollBar() : horizontalScrollBar();

		bar->setValue( bar->value() - event->delta() );
	}
	else
		View::wheelEvent(event);
}

qreal MainView::scaleFactor() const
{
	if (scaleLevel < SCALING_FACTOR)
		return SCALING_FACTOR / (qreal) scaleLevel;
	else return std::pow(2, SCALING_FACTOR - scaleLevel);
}

void MainView::scrollContentsBy(int dx, int dy)
{
	View::scrollContentsBy(dx, dy);
	if ( miniMap ) miniMap->visibleRectChanged();
}

void MainView::keyPressEvent(QKeyEvent *event)
{
	if ( (event->modifiers() & Qt::ControlModifier || event->modifiers() & Qt::ShiftModifier)
			&& event->key() == Qt::Key_Print)
	{
		event->accept();
		scene()->setHiddenItemCategories(0);
		if (scene()->mainCursor() && scene()->mainCursor()->visualization())
			scene()->mainCursor()->visualization()->hide();

		QPrinter printer;
		printer.setOutputFormat(QPrinter::PdfFormat);
		printer.setFullPage(true);
		printer.setResolution(300);

		QSvgGenerator svggen;
		svggen.setResolution(90);

		bool ownerIgnoresScale = setCursorAndOwnerIgnoreScaleForScreenShot(false, false);

		if (event->modifiers() & Qt::ShiftModifier)
		{
			// Print scene
			VisualizationBasePlugin::log().info("Capturing a screenshot of the entire scene.");

			printer.setOutputFileName("screenshot-scene.pdf");
			printer.setPaperSize(scene()->sceneRect().size().toSize(), QPrinter::Point);
			QPainter painter{&printer};
			painter.setRenderHint(QPainter::Antialiasing);
			scene()->render( &painter );

			svggen.setFileName("screenshot-scene.svg");
			svggen.setSize(scene()->sceneRect().size().toSize());
			QPainter svgPainter{&svggen};
			svgPainter.setRenderHint(QPainter::Antialiasing);
			scene()->render(&svgPainter);

			QImage image{PNG_SCREENSHOT_SCALE * scene()->sceneRect().size().toSize(), QImage::Format_ARGB32};
			image.fill(Qt::transparent);
			QPainter pmapPainter{&image};
			pmapPainter.setRenderHint(QPainter::Antialiasing);
			//pmapPainter.scale(2, 2);
			scene()->render(&pmapPainter);
			image.save("screenshot-scene.png");
		}
		else
		{
			// Print view
			VisualizationBasePlugin::log().info("Capturing a screenshot of the current view.");

			printer.setOutputFileName("screenshot-view.pdf");
			printer.setPaperSize(viewport()->rect().size(), QPrinter::Point);
			QPainter painter{&printer};
			painter.setRenderHint(QPainter::Antialiasing);
			render(&painter);

			svggen.setFileName("screenshot-view.svg");
			svggen.setSize(viewport()->rect().size());
			QPainter svgPainter{&svggen};
			svgPainter.setRenderHint(QPainter::Antialiasing);
			render(&svgPainter);

			QImage image{PNG_SCREENSHOT_SCALE * viewport()->rect().size(), QImage::Format_ARGB32};
			image.fill(Qt::transparent);
			QPainter pmapPainter{&image};
			pmapPainter.setRenderHint(QPainter::Antialiasing);
			render(&pmapPainter);
			image.save("screenshot-view.png");
		}

		setCursorAndOwnerIgnoreScaleForScreenShot(true, ownerIgnoresScale);
	}
	else if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier) && event->key() == Qt::Key_P)
	{
		// Toggle presentation mode (full screen + no scroll bars + no minimap)

		event->accept();
		QWidget* window = this;
		while (window->parentWidget()) window = window->parentWidget();

		if (window->isFullScreen())
		{
			window->showNormal();
			setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
			setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
			miniMap->show();
		}
		else
		{
			window->showFullScreen();
			setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
			setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
			miniMap->hide();
		}
	}
	else if (event->modifiers() == Qt::NoModifier && event->key() == Qt::Key_F11)
	{
		// Toggle fullscreen only
		event->accept();
		QWidget* window = this;
		while (window->parentWidget()) window = window->parentWidget();

		if (window->isFullScreen()) window->showNormal();
		else window->showFullScreen();
	}
	else if (event->modifiers() == Qt::NoModifier && event->key() == Qt::Key_F10)
	{
		event->accept();
		if (miniMap->width() == MINIMAP_DEFAULT_WIDTH && miniMap->height() ==  MINIMAP_DEFAULT_HEIGHT)
			setMiniMapSize(width(), height());
		else setMiniMapSize(MINIMAP_DEFAULT_WIDTH, MINIMAP_DEFAULT_HEIGHT);
	}
	else if (event->modifiers() == Qt::NoModifier && event->key() == Qt::Key_F9)
	{
		event->accept();
		if (miniMap->isVisible()) miniMap->hide();
		else miniMap->show();
	}
	else if (event->modifiers() == Qt::NoModifier && event->key() == Qt::Key_F7)
	{
		event->accept();
		showTimers_ = ~showTimers_;
		updateInfoLabels();
	}
	else View::keyPressEvent(event);
}

void MainView::updateInfoLabels()
{
	if (!showTimers_)
	{
		if (!infoLabels_.isEmpty())
		{
			for (auto label : infoLabels_) SAFE_DELETE(label);
			infoLabels_.clear();
		}
		return;
	}

	int labelIndex = 0;
	int yPos = 10;

	// Add timers
	for (auto name : Logger::Timer::timerNames())
	{
		QLabel* label{};

		if (infoLabels_.size() <= labelIndex)
		{
			label = new QLabel{this};
			label->setAttribute(Qt::WA_TransparentForMouseEvents);
			infoLabels_.append(label);
			label->show();
			label->setStyleSheet("QLabel { color : red; }");
		}
		else label = infoLabels_.at(labelIndex);

		// Set the position of the label
		label->move(10, yPos);

		// Construct label text
		auto info = name + ":  ";
		for (auto val : Logger::Timer::timer(name)->values())
			info += QString::number(val) + "  ";

		label->setText(info);
		label->adjustSize();

		++labelIndex;
		yPos+=label->height();
	}

	// Remove unnecessary labels
	while (labelIndex < infoLabels_.size() )
	{
		SAFE_DELETE(infoLabels_.last());
		infoLabels_.removeLast();
	}
}

void MainView::paintEvent(QPaintEvent* event)
{
	auto t = Logger::Timer::start("Main view paint");
	View::paintEvent(event);
	t->tick();
}

void MainView::mouseMoveEvent(QMouseEvent *event)
{
	if (!isPanning_) return View::mouseMoveEvent(event);

	event->accept();
	horizontalScrollBar()->setValue(horizontalScrollBar()->value() - (event->x() - panStartPos_.x()));
	verticalScrollBar()->setValue(verticalScrollBar()->value() - (event->y() - panStartPos_.y()));
	panStartPos_ = event->pos();
}

void MainView::mousePressEvent(QMouseEvent *event)
{
	if (event->modifiers() != Qt::ControlModifier) return View::mousePressEvent(event);

	event->accept();
	isPanning_ = true;
	panStartPos_ = event->pos();
	setCursor(Qt::ClosedHandCursor);
}

void MainView::mouseReleaseEvent(QMouseEvent *event)
{
	if (!isPanning_) return View::mouseReleaseEvent(event);

	event->accept();
	setCursor(Qt::ArrowCursor);
	isPanning_ = false;
}

bool MainView::setCursorAndOwnerIgnoreScaleForScreenShot(bool ignore, bool modifyOwner)
{
	bool ownerIgnoresScale = false;

	auto cursor = scene()->mainCursor();
	if (cursor)
	{
		if ( auto vis = cursor->visualization() ) vis->setFlag(Item::ItemIgnoresTransformations, ignore);
		auto owner = cursor->owner();
		if (owner)
		{
			while (owner->parent()) owner = owner->parent();
			if (!ignore)
			{
				ownerIgnoresScale = owner->flags() & Item::ItemIgnoresTransformations;
				if (ownerIgnoresScale) owner->setFlag(Item::ItemIgnoresTransformations, false);
			}
			else if (modifyOwner) owner->setFlag(Item::ItemIgnoresTransformations, true);
		}
	}

	return ownerIgnoresScale;
}

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/bitcoin/wallet/mnemonic.hpp>

#include <algorithm>
#include <cstdint>
#include <boost/locale.hpp>
#include <bitcoin/bitcoin/define.hpp>
#include <bitcoin/bitcoin/math/external/pkcs5_pbkdf2.h>
#include <bitcoin/bitcoin/utility/assert.hpp>
#include <bitcoin/bitcoin/utility/binary.hpp>
#include <bitcoin/bitcoin/utility/general.hpp>
#include <bitcoin/bitcoin/wallet/dictionary.hpp>

namespace libbitcoin {
namespace bip39 {

// BIP-39 private constants.
constexpr size_t bits_per_word = 11;
constexpr size_t entropy_bit_divisor = 32;
constexpr size_t hmac_iterations = 2048;
DEBUG_ONLY(constexpr size_t dictionary_length = 2048;)

// It would be nice if we could do this statically.
static void validate_dictionary()
{
    BITCOIN_ASSERT_MSG(dictionary.size() == sizeof(bip39::language),
        "The dictionary does not have the required number of languages.");

#ifndef NDEBUG
    for (const auto& dictionary: bip39::dictionary)
    {
        BITCOIN_ASSERT_MSG(dictionary.second.size() == dictionary_length,
            "A dictionary does not have the required number of elements.");
    }
#endif
}

static const string_list& get_dictionary(bip39::language language)
{
    validate_dictionary();

    const auto it = bip39::dictionary.find(language);

    // Guards against lack of uniqueness in dictionary languages.
    BITCOIN_ASSERT(it != bip39::dictionary.end());
    return it->second;
}

static bip39::language get_language(const string_list& words)
{
    validate_dictionary();

    if (words.empty())
        return bip39::language::en;

    const auto& first_word = words.front();

    for (const auto& dictionary : bip39::dictionary)
        if (find_position(dictionary.second, first_word) != -1)
            return dictionary.first;

    return bip39::language::en;
}

static std::string normalize_nfkd(const std::string& value)
{
    using namespace boost::locale;
    const generator locale;
    return normalize(value, norm_type::norm_nfkd, locale(""));
}

static uint8_t bip39_shift(size_t bit)
{
    return (1 << (byte_bits - (bit % byte_bits) - 1));
}

// extracts entropy/checksum from the mnemonic and rebuilds the word list
// for comparison; returns true if it's a match (valid), false otherwise
static bool validate_mnemonic(const string_list& words,
    const string_list& dictionary, bip39::language language)
{
    const auto word_count = words.size();
    if ((word_count < min_word_count) || (word_count > max_word_count))
        return false;

    size_t bit = 0;
    data_chunk seed(max_word_count, 0);

    for (const auto& word: words)
    {
        const auto position = find_position(dictionary, word);
        if (position == -1)
            return false;

        for (size_t loop = 0; loop < bits_per_word; loop++, bit++)
        {
            if (position & (1 << (bits_per_word - loop - 1)))
            {
                const auto byte = bit / byte_bits;
                seed[byte] |= bip39_shift(bit);
            }
        }
    }

    const auto size = bit / byte_bits;
    seed.resize(size);

    const auto mnemonic = create_mnemonic(seed, language);
    return std::equal(mnemonic.begin(), mnemonic.end(), words.begin());
}

data_chunk decode_mnemonic(const string_list& mnemonic,
    const std::string& passphrase)
{
    const auto language = get_language(mnemonic);
    const auto& dictionary = get_dictionary(language);

    if (!validate_mnemonic(mnemonic, dictionary, language))
        return data_chunk();

    const auto sentence = join(mnemonic);
    const auto salt = normalize_nfkd("mnemonic" + passphrase);
    const auto salt_chunk = to_data_chunk(salt);

    long_hash hash;
    if (pkcs5_pbkdf2_hmac_sha512(sentence, salt_chunk, hmac_iterations, hash))
        return to_data_chunk(hash);

    return data_chunk();
}

string_list create_mnemonic(data_slice entropy, bip39::language language)
{
    if ((entropy.size() % seed_multiple) != 0)
        return string_list();

    const auto& dictionary = get_dictionary(language);
    const auto hash = sha256_hash(entropy);
    auto chunk = to_data_chunk(entropy);
    extend_data(chunk, hash);

    const size_t entropy_bits = (entropy.size() * byte_bits);
    const size_t check_bits = (entropy_bits / entropy_bit_divisor);
    const size_t total_bits = (entropy_bits + check_bits);
    const size_t word_count = (total_bits / bits_per_word);

    BITCOIN_ASSERT((total_bits % bits_per_word) == 0);
    BITCOIN_ASSERT((word_count % word_multiple) == 0);

    size_t bit = 0;
    string_list words;

    for (size_t word = 0; word < word_count; word++)
    {
        size_t position = 0;
        for (size_t loop = 0; loop < bits_per_word; loop++)
        {
            bit = (word * bits_per_word + loop);
            position <<= 1;

            const auto byte = bit / byte_bits;

            if ((chunk[byte] & bip39_shift(bit)) > 0)
                position++;
        }

        BITCOIN_ASSERT(position < dictionary_length);
        words.push_back(dictionary[position]);
    }

    BITCOIN_ASSERT(words.size() == (bit / bits_per_word));
    return words;
}

} // namespace bip39
} // namespace libbitcoin

<commit_msg>- fix off by one bug on assertion<commit_after>/*
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/bitcoin/wallet/mnemonic.hpp>

#include <algorithm>
#include <cstdint>
#include <boost/locale.hpp>
#include <bitcoin/bitcoin/define.hpp>
#include <bitcoin/bitcoin/math/external/pkcs5_pbkdf2.h>
#include <bitcoin/bitcoin/utility/assert.hpp>
#include <bitcoin/bitcoin/utility/binary.hpp>
#include <bitcoin/bitcoin/utility/general.hpp>
#include <bitcoin/bitcoin/wallet/dictionary.hpp>

namespace libbitcoin {
namespace bip39 {

// BIP-39 private constants.
constexpr size_t bits_per_word = 11;
constexpr size_t entropy_bit_divisor = 32;
constexpr size_t hmac_iterations = 2048;
DEBUG_ONLY(constexpr size_t dictionary_length = 2048;)

// It would be nice if we could do this statically.
static void validate_dictionary()
{
    BITCOIN_ASSERT_MSG(dictionary.size() == sizeof(bip39::language),
        "The dictionary does not have the required number of languages.");

#ifndef NDEBUG
    for (const auto& dictionary: bip39::dictionary)
    {
        BITCOIN_ASSERT_MSG(dictionary.second.size() == dictionary_length,
            "A dictionary does not have the required number of elements.");
    }
#endif
}

static const string_list& get_dictionary(bip39::language language)
{
    validate_dictionary();

    const auto it = bip39::dictionary.find(language);

    // Guards against lack of uniqueness in dictionary languages.
    BITCOIN_ASSERT(it != bip39::dictionary.end());
    return it->second;
}

static bip39::language get_language(const string_list& words)
{
    validate_dictionary();

    if (words.empty())
        return bip39::language::en;

    const auto& first_word = words.front();

    for (const auto& dictionary : bip39::dictionary)
        if (find_position(dictionary.second, first_word) != -1)
            return dictionary.first;

    return bip39::language::en;
}

static std::string normalize_nfkd(const std::string& value)
{
    using namespace boost::locale;
    const generator locale;
    return normalize(value, norm_type::norm_nfkd, locale(""));
}

static uint8_t bip39_shift(size_t bit)
{
    return (1 << (byte_bits - (bit % byte_bits) - 1));
}

// extracts entropy/checksum from the mnemonic and rebuilds the word list
// for comparison; returns true if it's a match (valid), false otherwise
static bool validate_mnemonic(const string_list& words,
    const string_list& dictionary, bip39::language language)
{
    const auto word_count = words.size();
    if ((word_count < min_word_count) || (word_count > max_word_count))
        return false;

    size_t bit = 0;
    data_chunk seed(max_word_count, 0);

    for (const auto& word: words)
    {
        const auto position = find_position(dictionary, word);
        if (position == -1)
            return false;

        for (size_t loop = 0; loop < bits_per_word; loop++, bit++)
        {
            if (position & (1 << (bits_per_word - loop - 1)))
            {
                const auto byte = bit / byte_bits;
                seed[byte] |= bip39_shift(bit);
            }
        }
    }

    const auto size = bit / byte_bits;
    seed.resize(size);

    const auto mnemonic = create_mnemonic(seed, language);
    return std::equal(mnemonic.begin(), mnemonic.end(), words.begin());
}

data_chunk decode_mnemonic(const string_list& mnemonic,
    const std::string& passphrase)
{
    const auto language = get_language(mnemonic);
    const auto& dictionary = get_dictionary(language);

    if (!validate_mnemonic(mnemonic, dictionary, language))
        return data_chunk();

    const auto sentence = join(mnemonic);
    const auto salt = normalize_nfkd("mnemonic" + passphrase);
    const auto salt_chunk = to_data_chunk(salt);

    long_hash hash;
    if (pkcs5_pbkdf2_hmac_sha512(sentence, salt_chunk, hmac_iterations, hash))
        return to_data_chunk(hash);

    return data_chunk();
}

string_list create_mnemonic(data_slice entropy, bip39::language language)
{
    if ((entropy.size() % seed_multiple) != 0)
        return string_list();

    const auto& dictionary = get_dictionary(language);
    const auto hash = sha256_hash(entropy);
    auto chunk = to_data_chunk(entropy);
    extend_data(chunk, hash);

    const size_t entropy_bits = (entropy.size() * byte_bits);
    const size_t check_bits = (entropy_bits / entropy_bit_divisor);
    const size_t total_bits = (entropy_bits + check_bits);
    const size_t word_count = (total_bits / bits_per_word);

    BITCOIN_ASSERT((total_bits % bits_per_word) == 0);
    BITCOIN_ASSERT((word_count % word_multiple) == 0);

    size_t bit = 0;
    string_list words;

    for (size_t word = 0; word < word_count; word++)
    {
        size_t position = 0;
        for (size_t loop = 0; loop < bits_per_word; loop++)
        {
            bit = (word * bits_per_word + loop);
            position <<= 1;

            const auto byte = bit / byte_bits;

            if ((chunk[byte] & bip39_shift(bit)) > 0)
                position++;
        }

        BITCOIN_ASSERT(position < dictionary_length);
        words.push_back(dictionary[position]);
    }

    BITCOIN_ASSERT(words.size() == ((bit + 1) / bits_per_word));
    return words;
}

} // namespace bip39
} // namespace libbitcoin

<|endoftext|>


<commit_before>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessn and Per Larsson
 *
 *                                                         Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/widgets/listbox.hpp"

#include "guichan/basiccontainer.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/listmodel.hpp"
#include "guichan/mouseinput.hpp"
#include "guichan/selectionlistener.hpp"

namespace gcn
{
    ListBox::ListBox()
        : mSelected(-1),
          mListModel(NULL),
          mWrappingEnabled(false)
    {
        setWidth(100);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    ListBox::ListBox(ListModel *listModel)
        : mSelected(-1),
          mWrappingEnabled(false)
    {
        setWidth(100);
        setListModel(listModel);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    void ListBox::draw(Graphics* graphics)
    {
        graphics->setColor(getBackgroundColor());
        graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));

        if (mListModel == NULL)
        {
            return;
        }

        graphics->setColor(getForegroundColor());
        graphics->setFont(getFont());

        // Check the current clip area so we don't draw unnecessary items
        // that are not visible.
        const ClipRectangle currentClipArea = graphics->getCurrentClipArea();
        int fontHeight = getFont()->getHeight();
        int i = currentClipArea.y / getFont()->getHeight();
        int end = (currentClipArea.y + currentClipArea.height) / getFont()->getHeight();

        if (end >= mListModel->getNumberOfElements())
        {
            end = mListModel->getNumberOfElements() - 1;
        }

        int y = 0;

        for (i = 0; i < end; ++i)
        {
            if (i == mSelected)
            {
                graphics->setColor(getSelectionColor());
                graphics->fillRectangle(Rectangle(0, y, getWidth(), fontHeight));
                graphics->setColor(getForegroundColor());
            }

            graphics->drawText(mListModel->getElementAt(i), 1, y);

            y += fontHeight;
        }
    }

    void ListBox::logic()
    {
        adjustSize();
    }

    int ListBox::getSelected() const
    {
        return mSelected;
    }

    void ListBox::setSelected(int selected)
    {
        if (mListModel == NULL)
        {
            mSelected = -1;
        }
        else
        {
            if (selected < 0)
            {
                mSelected = -1;
            }
            else if (selected >= mListModel->getNumberOfElements())
            {
                mSelected = mListModel->getNumberOfElements() - 1;
            }
            else
            {
                mSelected = selected;
            }

            Widget *par = getParent();
            if (par == NULL)
            {
                return;
            }

            Rectangle scroll;

            if (mSelected < 0)
            {
                scroll.y = 0;
            }
            else
            {
                scroll.y = getFont()->getHeight() * mSelected;
            }

            scroll.height = getFont()->getHeight();
            par->showWidgetPart(this, scroll);
        }

        distributeValueChangedEvent();
    }

    void ListBox::keyPressed(KeyEvent& keyEvent)
    {
        Key key = keyEvent.getKey();

        if (key.getValue() == Key::ENTER || key.getValue() == Key::SPACE)
        {
            distributeActionEvent();
            keyEvent.consume();
        }
        else if (key.getValue() == Key::UP)
        {
            setSelected(mSelected - 1);

            if (mSelected == -1)
            {
                if (mWrappingEnabled)
                {
                    setSelected(getListModel()->getNumberOfElements() - 1);
                }
                else
                {
                    setSelected(0);
                }
            }

            keyEvent.consume();
        }
        else if (key.getValue() == Key::DOWN)
        {
            if (mWrappingEnabled
                && getSelected() == getListModel()->getNumberOfElements() - 1)
            {
                setSelected(0);
            }
            else
            {
                setSelected(getSelected() + 1);
            }

            keyEvent.consume();
        }
        else if (key.getValue() == Key::HOME)
        {
            setSelected(0);
            keyEvent.consume();
        }
        else if (key.getValue() == Key::END)
        {
            setSelected(getListModel()->getNumberOfElements() - 1);
            keyEvent.consume();
        }
    }

    void ListBox::mousePressed(MouseEvent& mouseEvent)
    {
        if (mouseEvent.getButton() == MouseEvent::LEFT)
        {
            setSelected(mouseEvent.getY() / getFont()->getHeight());
            distributeActionEvent();
        }
    }

    void ListBox::mouseWheelMovedUp(MouseEvent& mouseEvent)
    {
        if (isFocused())
        {
            if (getSelected() > 0 )
            {
                setSelected(getSelected() - 1);
            }

            mouseEvent.consume();
        }
    }

    void ListBox::mouseWheelMovedDown(MouseEvent& mouseEvent)
    {
        if (isFocused())
        {
            setSelected(getSelected() + 1);

            mouseEvent.consume();
        }
    }

    void ListBox::mouseDragged(MouseEvent& mouseEvent)
    {
        mouseEvent.consume();
    }

    void ListBox::setListModel(ListModel *listModel)
    {
        mSelected = -1;
        mListModel = listModel;
        adjustSize();
    }

    ListModel* ListBox::getListModel()
    {
        return mListModel;
    }

    void ListBox::adjustSize()
    {
        if (mListModel != NULL)
        {
            setHeight(getFont()->getHeight() * mListModel->getNumberOfElements());
        }
    }

    bool ListBox::isWrappingEnabled() const
    {
        return mWrappingEnabled;
    }

    void ListBox::setWrappingEnabled(bool wrappingEnabled)
    {
        mWrappingEnabled = wrappingEnabled;
    }

    void ListBox::addSelectionListener(SelectionListener* selectionListener)
    {
        mSelectionListeners.push_back(selectionListener);
    }

    void ListBox::removeSelectionListener(SelectionListener* selectionListener)
    {
        mSelectionListeners.remove(selectionListener);
    }

    void ListBox::distributeValueChangedEvent()
    {
        SelectionListenerIterator iter;

        for (iter = mSelectionListeners.begin(); iter != mSelectionListeners.end(); ++iter)
        {
            SelectionEvent event(this);
            (*iter)->valueChanged(event);
        }
    }
}
<commit_msg>Bug fix in list box has been applied where list box might have tried to retrieve an item outside of the index range of the list model.<commit_after>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessn and Per Larsson
 *
 *                                                         Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/widgets/listbox.hpp"

#include "guichan/basiccontainer.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/listmodel.hpp"
#include "guichan/mouseinput.hpp"
#include "guichan/selectionlistener.hpp"

namespace gcn
{
    ListBox::ListBox()
        : mSelected(-1),
          mListModel(NULL),
          mWrappingEnabled(false)
    {
        setWidth(100);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    ListBox::ListBox(ListModel *listModel)
        : mSelected(-1),
          mWrappingEnabled(false)
    {
        setWidth(100);
        setListModel(listModel);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    void ListBox::draw(Graphics* graphics)
    {
        graphics->setColor(getBackgroundColor());
        graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));

        if (mListModel == NULL)
        {
            return;
        }

        graphics->setColor(getForegroundColor());
        graphics->setFont(getFont());

        // Check the current clip area so we don't draw unnecessary items
        // that are not visible.
        const ClipRectangle currentClipArea = graphics->getCurrentClipArea();
        int fontHeight = getFont()->getHeight();
        int i = currentClipArea.y / getFont()->getHeight();
        int end = (currentClipArea.y + currentClipArea.height) / getFont()->getHeight();

        if (end > mListModel->getNumberOfElements())
        {
            end = mListModel->getNumberOfElements();
        }

        int y = 0;

        for (i = 0; i < end; ++i)
        {
            if (i == mSelected)
            {
                graphics->setColor(getSelectionColor());
                graphics->fillRectangle(Rectangle(0, y, getWidth(), fontHeight));
                graphics->setColor(getForegroundColor());
            }

            graphics->drawText(mListModel->getElementAt(i), 1, y);

            y += fontHeight;
        }
    }

    void ListBox::logic()
    {
        adjustSize();
    }

    int ListBox::getSelected() const
    {
        return mSelected;
    }

    void ListBox::setSelected(int selected)
    {
        if (mListModel == NULL)
        {
            mSelected = -1;
        }
        else
        {
            if (selected < 0)
            {
                mSelected = -1;
            }
            else if (selected >= mListModel->getNumberOfElements())
            {
                mSelected = mListModel->getNumberOfElements() - 1;
            }
            else
            {
                mSelected = selected;
            }

            Widget *par = getParent();
            if (par == NULL)
            {
                return;
            }

            Rectangle scroll;

            if (mSelected < 0)
            {
                scroll.y = 0;
            }
            else
            {
                scroll.y = getFont()->getHeight() * mSelected;
            }

            scroll.height = getFont()->getHeight();
            par->showWidgetPart(this, scroll);
        }

        distributeValueChangedEvent();
    }

    void ListBox::keyPressed(KeyEvent& keyEvent)
    {
        Key key = keyEvent.getKey();

        if (key.getValue() == Key::ENTER || key.getValue() == Key::SPACE)
        {
            distributeActionEvent();
            keyEvent.consume();
        }
        else if (key.getValue() == Key::UP)
        {
            setSelected(mSelected - 1);

            if (mSelected == -1)
            {
                if (mWrappingEnabled)
                {
                    setSelected(getListModel()->getNumberOfElements() - 1);
                }
                else
                {
                    setSelected(0);
                }
            }

            keyEvent.consume();
        }
        else if (key.getValue() == Key::DOWN)
        {
            if (mWrappingEnabled
                && getSelected() == getListModel()->getNumberOfElements() - 1)
            {
                setSelected(0);
            }
            else
            {
                setSelected(getSelected() + 1);
            }

            keyEvent.consume();
        }
        else if (key.getValue() == Key::HOME)
        {
            setSelected(0);
            keyEvent.consume();
        }
        else if (key.getValue() == Key::END)
        {
            setSelected(getListModel()->getNumberOfElements() - 1);
            keyEvent.consume();
        }
    }

    void ListBox::mousePressed(MouseEvent& mouseEvent)
    {
        if (mouseEvent.getButton() == MouseEvent::LEFT)
        {
            setSelected(mouseEvent.getY() / getFont()->getHeight());
            distributeActionEvent();
        }
    }

    void ListBox::mouseWheelMovedUp(MouseEvent& mouseEvent)
    {
        if (isFocused())
        {
            if (getSelected() > 0 )
            {
                setSelected(getSelected() - 1);
            }

            mouseEvent.consume();
        }
    }

    void ListBox::mouseWheelMovedDown(MouseEvent& mouseEvent)
    {
        if (isFocused())
        {
            setSelected(getSelected() + 1);

            mouseEvent.consume();
        }
    }

    void ListBox::mouseDragged(MouseEvent& mouseEvent)
    {
        mouseEvent.consume();
    }

    void ListBox::setListModel(ListModel *listModel)
    {
        mSelected = -1;
        mListModel = listModel;
        adjustSize();
    }

    ListModel* ListBox::getListModel()
    {
        return mListModel;
    }

    void ListBox::adjustSize()
    {
        if (mListModel != NULL)
        {
            setHeight(getFont()->getHeight() * mListModel->getNumberOfElements());
        }
    }

    bool ListBox::isWrappingEnabled() const
    {
        return mWrappingEnabled;
    }

    void ListBox::setWrappingEnabled(bool wrappingEnabled)
    {
        mWrappingEnabled = wrappingEnabled;
    }

    void ListBox::addSelectionListener(SelectionListener* selectionListener)
    {
        mSelectionListeners.push_back(selectionListener);
    }

    void ListBox::removeSelectionListener(SelectionListener* selectionListener)
    {
        mSelectionListeners.remove(selectionListener);
    }

    void ListBox::distributeValueChangedEvent()
    {
        SelectionListenerIterator iter;

        for (iter = mSelectionListeners.begin(); iter != mSelectionListeners.end(); ++iter)
        {
            SelectionEvent event(this);
            (*iter)->valueChanged(event);
        }
    }
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/wkt/wkt_grammar.hpp>
// stl
#include <string>

namespace mapnik
{

bool from_wkt(std::string const& wkt, boost::ptr_vector<geometry_type> & paths)
{
    using namespace boost::spirit;
    typedef std::string::const_iterator iterator_type;
    iterator_type first = wkt.begin();
    iterator_type last =  wkt.end();
    mapnik::wkt::wkt_collection_grammar<iterator_type> grammar;
    return qi::phrase_parse(first, last, grammar, ascii::space, paths);
}

}

<commit_msg>maintain boost 1.42 compatibility by disabling new wkt parser for boost <= 1.46<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// boost
#include <boost/version.hpp>

// mapnik
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/wkt/wkt_grammar.hpp>

// stl
#include <string>
#include <sstream>

namespace mapnik
{

bool from_wkt(std::string const& wkt, boost::ptr_vector<geometry_type> & paths)
{
#if BOOST_VERSION >= 104700
    using namespace boost::spirit;
    typedef std::string::const_iterator iterator_type;
    iterator_type first = wkt.begin();
    iterator_type last =  wkt.end();
    mapnik::wkt::wkt_collection_grammar<iterator_type> grammar;
    return qi::phrase_parse(first, last, grammar, ascii::space, paths);
#else
    // TODO - remove this after mapnik 2.0.0 release
    std::ostringstream s;
    s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000  << "." << BOOST_VERSION % 100;
    throw std::runtime_error("mapnik::from_wkt() requires at least boost 1.47 while your build was compiled against boost " + s.str());
    return false;
#endif
}

}

<|endoftext|>