<commit_before>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2020 musikcube team
//
// 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 author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "LruDiskCache.h"

#include <algorithm>

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

const std::string PREFIX = "musikcube";
const std::string TEMP_EXTENSION = ".tmp";

namespace fs = boost::filesystem;
namespace al = boost::algorithm;

using Lock = std::unique_lock<std::recursive_mutex>;

static std::string tempFilename(const std::string& root, size_t id) {
    return root + "/" + PREFIX + "_" + std::to_string(id) + TEMP_EXTENSION;
}

static std::string finalFilename(const std::string& root, size_t id, std::string type) {
    al::replace_all(type, "/", "-");
    return root + "/" + PREFIX + "_" + std::to_string(id) + "_" + type;
}

static bool isTemp(const fs::path& path) {
    return path.extension().string() == TEMP_EXTENSION;
}

static bool isTemp(const std::string& path) {
    return isTemp(fs::path(path));
}

static time_t touch(const std::string& path) {
    try {
        std::time_t now = time(nullptr);
        fs::last_write_time(path, now);
    }
    catch (...) {
    }

    return fs::last_write_time(path);
}

static bool rm(const std::string& path) {
    try {
        return fs::remove(fs::path(path));
    }
    catch (...) {

    }

    return false;
}

static bool rm(const fs::path& p) {
    return rm(p.string());
}

LruDiskCache::LruDiskCache()
: maxEntries(10)
, initialized(false) {

}

void LruDiskCache::Init(const std::string& root, size_t maxEntries) {
    Lock lock(this->stateMutex);

    if (!this->initialized) {
        this->initialized = true;
        this->root = root;
        this->maxEntries = maxEntries;

        this->Purge(); /* always purge partial files on startup */

        /* index all the completed files... */
        fs::directory_iterator end;
        fs::directory_iterator file(this->root);

        while (file != end) {
            if (!is_directory(file->status())) {
                if (!isTemp(file->path())) {
                    auto entry = LruDiskCache::Parse(file->path());
                    if (entry) {
                        this->cached.push_back(entry);
                    }
                }
            }
            ++file;
        }

        this->SortAndPrune();
    }
}

void LruDiskCache::Purge() {
    Lock lock(stateMutex);

    fs::directory_iterator end;
    fs::directory_iterator file(this->root);

    while (file != end) {
        if (!is_directory(file->status())) {
            if (isTemp(file->path())) {
                rm(file->path());
            }
        }
        ++file;
    }
}

LruDiskCache::EntryPtr LruDiskCache::Parse(const fs::path& path) {
    std::string fn = path.stem().string() + path.extension().string();
    std::vector<std::string> parts;
    boost::split(parts, fn, boost::is_any_of("_"));
    if (parts.size() == 3 && parts[0] == PREFIX) {
        try {
            auto entry = std::shared_ptr<Entry>(new Entry());
            entry->id = std::stoull(parts[1].c_str());
            entry->path = path.string();
            entry->type = parts[2];
            entry->time = fs::last_write_time(path);
            al::replace_all(entry->type, "-", "/");
            return entry;
        }
        catch (...) {
            /* can't parse. it's invalid. */
        }
    }

    return EntryPtr();
}

bool LruDiskCache::Finalize(size_t id, std::string type) {
    Lock lock(stateMutex);

    if (type.size() == 0) {
        type = "unknown";
    }

    fs::path src(tempFilename(this->root, id));
    fs::path dst(finalFilename(this->root, id, type));

    if (fs::exists(src)) {
        if (fs::exists(dst)) {
            if (!rm(dst)) {
                return false;
            }
        }

        try {
            fs::rename(src, dst);
        }
        catch (...) {
            return false;
        }

        auto entry = LruDiskCache::Parse(dst);
        if (entry) {
            this->cached.push_back(entry);
            this->SortAndPrune();
        }
    }

    return true;
}

bool LruDiskCache::Cached(size_t id) {
    Lock lock(stateMutex);

    auto end = this->cached.end();
    auto it = std::find_if(this->cached.begin(), end, [id](EntryPtr entry) {
        return entry->id == id;
    });

    return it != end;
}

FILE* LruDiskCache::Open(size_t id, const std::string& mode) {
    std::string type;
    size_t len;
    return this->Open(id, mode, type, len);
}

FILE* LruDiskCache::Open(size_t id, const std::string& mode, std::string& type, size_t& len) {
    Lock lock(stateMutex);

    auto end = this->cached.end();
    auto it = std::find_if(this->cached.begin(), end, [id](EntryPtr entry) {
        return entry->id == id;
    });

    FILE* result = nullptr;

    if (it != end) {
        result = fopen((*it)->path.c_str(), mode.c_str());

        if (result) {
            type = (*it)->type;
            fseek(result, 0, SEEK_END);
            len = (size_t) ftell(result);
            fseek(result, 0, SEEK_SET);
        }

        this->Touch(id);
    }

    /* open the file and return it regardless of cache status. */
    return result ? result : fopen(tempFilename(this->root, id).c_str(), mode.c_str());
}

void LruDiskCache::Delete(size_t id) {
    Lock lock(stateMutex);

    auto it = this->cached.begin();
    while (it != this->cached.end()) {
        if ((*it)->id == id) {
            rm((*it)->path);
            return;
        }
        else {
            ++it;
        }
    }

    rm(tempFilename(this->root, id));
}

void LruDiskCache::SortAndPrune() {
    Lock lock(this->stateMutex);

    std::sort( /* sort by access time */
        this->cached.begin(),
        this->cached.end(),
        [](EntryPtr e1, EntryPtr e2) {
            return e1->time > e2->time;
        });

    /* prune old entries */
    int count = (int) this->cached.size();
    int extras = count - this->maxEntries;
    for (int i = 0; i < extras; i++) {
        auto entry = this->cached.back();
        if (rm(this->root + "/" + entry->path)) {
            this->cached.pop_back();
        }
    }
}

void LruDiskCache::Touch(size_t id) {
    Lock lock(this->stateMutex);

    auto end = this->cached.end();
    auto it = std::find_if(this->cached.begin(), end, [id](EntryPtr entry) {
        return entry->id == id;
    });

    if (it != end) {
        auto e = (*it);
        fs::path p(e->path);
        if (boost::filesystem::exists(p)) {
            e->time = touch(p.string());
            this->SortAndPrune();
            return;
        }
    }
}<commit_msg>Fix LRU disk cache on Windows. Not sure how this was ever working on Unix, so we need to check it again.<commit_after>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2020 musikcube team
//
// 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 author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "LruDiskCache.h"

#include <algorithm>

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

const std::string PREFIX = "musikcube";
const std::string TEMP_EXTENSION = ".tmp";

namespace fs = boost::filesystem;
namespace al = boost::algorithm;

using Lock = std::unique_lock<std::recursive_mutex>;

static std::string tempFilename(const std::string& root, size_t id) {
    return root + "/" + PREFIX + "_" + std::to_string(id) + TEMP_EXTENSION;
}

static std::string finalFilename(const std::string& root, size_t id, std::string type) {
    al::replace_all(type, "/", "-");
    return root + "/" + PREFIX + "_" + std::to_string(id) + "_" + type;
}

static bool isTemp(const fs::path& path) {
    return path.extension().string() == TEMP_EXTENSION;
}

static bool isTemp(const std::string& path) {
    return isTemp(fs::path(path));
}

static time_t touch(const std::string& path) {
    try {
        std::time_t now = time(nullptr);
        fs::last_write_time(path, now);
    }
    catch (...) {
    }

    return fs::last_write_time(path);
}

static bool rm(const std::string& path) {
    try {
        return fs::remove(fs::path(path));
    }
    catch (...) {

    }

    return false;
}

static bool rm(const fs::path& p) {
    return rm(p.string());
}

LruDiskCache::LruDiskCache()
: maxEntries(10)
, initialized(false) {

}

void LruDiskCache::Init(const std::string& root, size_t maxEntries) {
    Lock lock(this->stateMutex);

    if (!this->initialized) {
        this->initialized = true;
        this->root = root;
        this->maxEntries = maxEntries;

        this->Purge(); /* always purge partial files on startup */

        /* index all the completed files... */
        fs::directory_iterator end;
        fs::directory_iterator file(this->root);

        while (file != end) {
            if (!is_directory(file->status())) {
                if (!isTemp(file->path())) {
                    auto entry = LruDiskCache::Parse(file->path());
                    if (entry) {
                        this->cached.push_back(entry);
                    }
                }
            }
            ++file;
        }

        this->SortAndPrune();
    }
}

void LruDiskCache::Purge() {
    Lock lock(stateMutex);

    fs::directory_iterator end;
    fs::directory_iterator file(this->root);

    while (file != end) {
        if (!is_directory(file->status())) {
            if (isTemp(file->path())) {
                rm(file->path());
            }
        }
        ++file;
    }
}

LruDiskCache::EntryPtr LruDiskCache::Parse(const fs::path& path) {
    std::string fn = path.stem().string() + path.extension().string();
    std::vector<std::string> parts;
    boost::split(parts, fn, boost::is_any_of("_"));
    if (parts.size() == 3 && parts[0] == PREFIX) {
        try {
            auto entry = std::shared_ptr<Entry>(new Entry());
            entry->id = std::stoull(parts[1].c_str());
            entry->path = path.string();
            entry->type = parts[2];
            entry->time = fs::last_write_time(path);
            al::replace_all(entry->type, "-", "/");
            return entry;
        }
        catch (...) {
            /* can't parse. it's invalid. */
        }
    }

    return EntryPtr();
}

bool LruDiskCache::Finalize(size_t id, std::string type) {
    Lock lock(stateMutex);

    if (type.size() == 0) {
        type = "unknown";
    }

    fs::path src(tempFilename(this->root, id));
    fs::path dst(finalFilename(this->root, id, type));

    if (fs::exists(src)) {
        if (fs::exists(dst)) {
            if (!rm(dst)) {
                return false;
            }
        }

        try {
            fs::rename(src, dst);
        }
        catch (...) {
            return false;
        }

        auto entry = LruDiskCache::Parse(dst);
        if (entry) {
            this->cached.push_back(entry);
            this->SortAndPrune();
        }
    }

    return true;
}

bool LruDiskCache::Cached(size_t id) {
    Lock lock(stateMutex);

    auto end = this->cached.end();
    auto it = std::find_if(this->cached.begin(), end, [id](EntryPtr entry) {
        return entry->id == id;
    });

    return it != end;
}

FILE* LruDiskCache::Open(size_t id, const std::string& mode) {
    std::string type;
    size_t len;
    return this->Open(id, mode, type, len);
}

FILE* LruDiskCache::Open(size_t id, const std::string& mode, std::string& type, size_t& len) {
    Lock lock(stateMutex);

    auto end = this->cached.end();
    auto it = std::find_if(this->cached.begin(), end, [id](EntryPtr entry) {
        return entry->id == id;
    });

    FILE* result = nullptr;

    if (it != end) {
        result = fopen((*it)->path.c_str(), mode.c_str());

        if (result) {
            type = (*it)->type;
            fseek(result, 0, SEEK_END);
            len = (size_t) ftell(result);
            fseek(result, 0, SEEK_SET);
        }

        this->Touch(id);
    }

    /* open the file and return it regardless of cache status. */
    return result ? result : fopen(tempFilename(this->root, id).c_str(), mode.c_str());
}

void LruDiskCache::Delete(size_t id) {
    Lock lock(stateMutex);

    auto it = this->cached.begin();
    while (it != this->cached.end()) {
        if ((*it)->id == id) {
            rm((*it)->path);
            return;
        }
        else {
            ++it;
        }
    }

    rm(tempFilename(this->root, id));
}

void LruDiskCache::SortAndPrune() {
    Lock lock(this->stateMutex);

    std::sort( /* sort by access time */
        this->cached.begin(),
        this->cached.end(),
        [](EntryPtr e1, EntryPtr e2) {
            return e1->time > e2->time;
        });

    /* prune old entries */
    int count = (int) this->cached.size();
    int extras = count - this->maxEntries;
    for (int i = 0; i < extras; i++) {
        auto entry = this->cached.back();
        if (rm(entry->path)) {
            this->cached.pop_back();
        }
    }
}

void LruDiskCache::Touch(size_t id) {
    Lock lock(this->stateMutex);

    auto end = this->cached.end();
    auto it = std::find_if(this->cached.begin(), end, [id](EntryPtr entry) {
        return entry->id == id;
    });

    if (it != end) {
        auto e = (*it);
        fs::path p(e->path);
        if (boost::filesystem::exists(p)) {
            e->time = touch(p.string());
            this->SortAndPrune();
            return;
        }
    }
}<|endoftext|>


<commit_before>#include "DebugHandStream.h"
#include <SenseKitUL/streams/hand_parameters.h>

namespace sensekit { namespace plugins { namespace hand {

    void DebugHandStream::on_set_parameter(sensekit_streamconnection_t connection,
                                           sensekit_parameter_id id,
                                           size_t inByteLength,
                                           sensekit_parameter_data_t inData)
    {
        switch (id)
        {
        case SENSEKIT_PARAMETER_DEBUG_HAND_VIEW_TYPE:
            set_view_parameter(inByteLength, inData);
            break;
        case SENSEKIT_PARAMETER_DEBUG_HAND_USE_MOUSE_PROBE:
            set_use_mouse_probe(inByteLength, inData);
            break;
        case SENSEKIT_PARAMETER_DEBUG_HAND_MOUSE_NORM_POSITION:
            set_mouse_norm_position(inByteLength, inData);
            break;
        }
    }

    void DebugHandStream::on_get_parameter(sensekit_streamconnection_t connection,
                                           sensekit_parameter_id id,
                                           sensekit_parameter_bin_t& parameterBin)
    {
        switch (id)
        {
        case SENSEKIT_PARAMETER_DEBUG_HAND_VIEW_TYPE:
            get_view_parameter(parameterBin);
            break;
        }
    }

    void DebugHandStream::on_invoke(sensekit_streamconnection_t connection,
                                    sensekit_command_id commandId,
                                    size_t inByteLength,
                                    sensekit_parameter_data_t inData,
                                    sensekit_parameter_bin_t& parameterBin)
    {
    }

    void DebugHandStream::get_view_parameter(sensekit_parameter_bin_t& parameterBin)
    {
        size_t resultByteLength = sizeof(DebugHandViewType);

        sensekit_parameter_data_t parameterData;
        sensekit_status_t rc = get_pluginService().get_parameter_bin(resultByteLength,
                                                                     &parameterBin,
                                                                     &parameterData);
        if (rc == SENSEKIT_STATUS_SUCCESS)
        {
            memcpy(parameterData, &m_viewType, resultByteLength);
        }
    }

    void DebugHandStream::set_view_parameter(size_t inByteLength, sensekit_parameter_data_t& inData)
    {
        if (inByteLength >= sizeof(DebugHandViewType))
        {
            DebugHandViewType newViewType;
            memcpy(&newViewType, inData, sizeof(DebugHandViewType));

            set_view_type(newViewType);
        }
    }

    void DebugHandStream::set_use_mouse_probe(size_t inByteLength, sensekit_parameter_data_t& inData)
    {
        if (inByteLength >= sizeof(bool))
        {
            bool newUseMouseProbe;
            memcpy(&newUseMouseProbe, inData, sizeof(bool));

            m_useMouseProbe = newUseMouseProbe;
        }
    }

    void DebugHandStream::set_mouse_norm_position(size_t inByteLength, sensekit_parameter_data_t& inData)
    {
        if (inByteLength >= sizeof(sensekit_vector2f_t))
        {
            sensekit_vector2f_t newMousePosition;
            memcpy(&newMousePosition, inData, sizeof(sensekit_vector2f_t));

            m_mouseNormPosition = reinterpret_cast<const Vector2f&>(newMousePosition);
        }
    }
}}}<commit_msg>Fix nasty cast<commit_after>#include "DebugHandStream.h"
#include <SenseKitUL/streams/hand_parameters.h>

namespace sensekit { namespace plugins { namespace hand {

    void DebugHandStream::on_set_parameter(sensekit_streamconnection_t connection,
                                           sensekit_parameter_id id,
                                           size_t inByteLength,
                                           sensekit_parameter_data_t inData)
    {
        switch (id)
        {
        case SENSEKIT_PARAMETER_DEBUG_HAND_VIEW_TYPE:
            set_view_parameter(inByteLength, inData);
            break;
        case SENSEKIT_PARAMETER_DEBUG_HAND_USE_MOUSE_PROBE:
            set_use_mouse_probe(inByteLength, inData);
            break;
        case SENSEKIT_PARAMETER_DEBUG_HAND_MOUSE_NORM_POSITION:
            set_mouse_norm_position(inByteLength, inData);
            break;
        }
    }

    void DebugHandStream::on_get_parameter(sensekit_streamconnection_t connection,
                                           sensekit_parameter_id id,
                                           sensekit_parameter_bin_t& parameterBin)
    {
        switch (id)
        {
        case SENSEKIT_PARAMETER_DEBUG_HAND_VIEW_TYPE:
            get_view_parameter(parameterBin);
            break;
        }
    }

    void DebugHandStream::on_invoke(sensekit_streamconnection_t connection,
                                    sensekit_command_id commandId,
                                    size_t inByteLength,
                                    sensekit_parameter_data_t inData,
                                    sensekit_parameter_bin_t& parameterBin)
    {
    }

    void DebugHandStream::get_view_parameter(sensekit_parameter_bin_t& parameterBin)
    {
        size_t resultByteLength = sizeof(DebugHandViewType);

        sensekit_parameter_data_t parameterData;
        sensekit_status_t rc = get_pluginService().get_parameter_bin(resultByteLength,
                                                                     &parameterBin,
                                                                     &parameterData);
        if (rc == SENSEKIT_STATUS_SUCCESS)
        {
            memcpy(parameterData, &m_viewType, resultByteLength);
        }
    }

    void DebugHandStream::set_view_parameter(size_t inByteLength, sensekit_parameter_data_t& inData)
    {
        if (inByteLength >= sizeof(DebugHandViewType))
        {
            DebugHandViewType newViewType;
            memcpy(&newViewType, inData, sizeof(DebugHandViewType));

            set_view_type(newViewType);
        }
    }

    void DebugHandStream::set_use_mouse_probe(size_t inByteLength, sensekit_parameter_data_t& inData)
    {
        if (inByteLength >= sizeof(bool))
        {
            bool newUseMouseProbe;
            memcpy(&newUseMouseProbe, inData, sizeof(bool));

            m_useMouseProbe = newUseMouseProbe;
        }
    }

    void DebugHandStream::set_mouse_norm_position(size_t inByteLength, sensekit_parameter_data_t& inData)
    {
        if (inByteLength >= sizeof(sensekit_vector2f_t))
        {
            sensekit_vector2f_t newMousePosition;
            memcpy(&newMousePosition, inData, sizeof(sensekit_vector2f_t));

            m_mouseNormPosition = *reinterpret_cast<const Vector2f*>(&newMousePosition);
        }
    }
}}}<|endoftext|>


<commit_before>
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBlurMaskFilter.h"
#include "SkBlurMask.h"
#include "SkBuffer.h"
#include "SkMaskFilter.h"

class SkBlurMaskFilterImpl : public SkMaskFilter {
public:
    SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle,
                         uint32_t flags);

    // overrides from SkMaskFilter
    virtual SkMask::Format getFormat();
    virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
                            SkIPoint* margin);
    virtual BlurType asABlur(BlurInfo*);

    // overrides from SkFlattenable
    virtual Factory getFactory();
    virtual void flatten(SkFlattenableWriteBuffer&);

    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);

private:
    SkScalar                    fRadius;
    SkBlurMaskFilter::BlurStyle fBlurStyle;
    uint32_t                    fBlurFlags;

    SkBlurMaskFilterImpl(SkFlattenableReadBuffer&);

    typedef SkMaskFilter INHERITED;
};

SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius,
                                       SkBlurMaskFilter::BlurStyle style,
                                       uint32_t flags) {
    if (radius <= 0 || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount
        || flags > SkBlurMaskFilter::kAll_BlurFlag) {
        return NULL;
    }

    return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags));
}

///////////////////////////////////////////////////////////////////////////////

SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius,
                                           SkBlurMaskFilter::BlurStyle style,
                                           uint32_t flags)
    : fRadius(radius), fBlurStyle(style), fBlurFlags(flags) {
#if 0
    fGamma = NULL;
    if (gammaScale) {
        fGamma = new U8[256];
        if (gammaScale > 0)
            SkBlurMask::BuildSqrGamma(fGamma, gammaScale);
        else
            SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale);
    }
#endif
    SkASSERT(radius >= 0);
    SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount);
    SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
}

SkMask::Format SkBlurMaskFilterImpl::getFormat() {
    return SkMask::kA8_Format;
}

bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
                                      const SkMatrix& matrix, SkIPoint* margin) {
    SkScalar radius;
    if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
        radius = fRadius;
    } else {
        radius = matrix.mapRadius(fRadius);
    }

    // To avoid unseemly allocation requests (esp. for finite platforms like
    // handset) we limit the radius so something manageable. (as opposed to
    // a request like 10,000)
    static const SkScalar MAX_RADIUS = SkIntToScalar(128);
    radius = SkMinScalar(radius, MAX_RADIUS);
    SkBlurMask::Quality blurQuality =
        (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
            SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality;

#if defined(SK_BLUR_MASK_FILTER_IGNORE_MARGIN_FIX)
    if (SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
                         blurQuality)) {
        if (margin) {
            // we need to integralize radius for our margin, so take the ceil
            // just to be safe.
            margin->set(SkScalarCeil(radius), SkScalarCeil(radius));
        }
        return true;
    }
    return false;
#else
    return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
                            blurQuality, margin);
#endif
}

SkFlattenable* SkBlurMaskFilterImpl::CreateProc(SkFlattenableReadBuffer& buffer) {
    return SkNEW_ARGS(SkBlurMaskFilterImpl, (buffer));
}

SkFlattenable::Factory SkBlurMaskFilterImpl::getFactory() {
    return CreateProc;
}

SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer)
        : SkMaskFilter(buffer) {
    fRadius = buffer.readScalar();
    fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readS32();
    fBlurFlags = buffer.readU32() & SkBlurMaskFilter::kAll_BlurFlag;
    SkASSERT(fRadius >= 0);
    SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
}

void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) {
    this->INHERITED::flatten(buffer);
    buffer.writeScalar(fRadius);
    buffer.write32(fBlurStyle);
    buffer.write32(fBlurFlags);
}

static const SkMaskFilter::BlurType gBlurStyle2BlurType[] = {
    SkMaskFilter::kNormal_BlurType,
    SkMaskFilter::kSolid_BlurType,
    SkMaskFilter::kOuter_BlurType,
    SkMaskFilter::kInner_BlurType,
};

SkMaskFilter::BlurType SkBlurMaskFilterImpl::asABlur(BlurInfo* info) {
    if (info) {
        info->fRadius = fRadius;
        info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag);
        info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag);
    }
    return gBlurStyle2BlurType[fBlurStyle];
}

///////////////////////////////////////////////////////////////////////////////

static SkFlattenable::Registrar gReg("SkBlurMaskFilter",
                                     SkBlurMaskFilterImpl::CreateProc);

<commit_msg>Now that layout tests are fixed, remove flag to ignore margin fix. http://codereview.appspot.com/5186044/<commit_after>
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBlurMaskFilter.h"
#include "SkBlurMask.h"
#include "SkBuffer.h"
#include "SkMaskFilter.h"

class SkBlurMaskFilterImpl : public SkMaskFilter {
public:
    SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle,
                         uint32_t flags);

    // overrides from SkMaskFilter
    virtual SkMask::Format getFormat();
    virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
                            SkIPoint* margin);
    virtual BlurType asABlur(BlurInfo*);

    // overrides from SkFlattenable
    virtual Factory getFactory();
    virtual void flatten(SkFlattenableWriteBuffer&);

    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);

private:
    SkScalar                    fRadius;
    SkBlurMaskFilter::BlurStyle fBlurStyle;
    uint32_t                    fBlurFlags;

    SkBlurMaskFilterImpl(SkFlattenableReadBuffer&);

    typedef SkMaskFilter INHERITED;
};

SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius,
                                       SkBlurMaskFilter::BlurStyle style,
                                       uint32_t flags) {
    if (radius <= 0 || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount
        || flags > SkBlurMaskFilter::kAll_BlurFlag) {
        return NULL;
    }

    return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags));
}

///////////////////////////////////////////////////////////////////////////////

SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius,
                                           SkBlurMaskFilter::BlurStyle style,
                                           uint32_t flags)
    : fRadius(radius), fBlurStyle(style), fBlurFlags(flags) {
#if 0
    fGamma = NULL;
    if (gammaScale) {
        fGamma = new U8[256];
        if (gammaScale > 0)
            SkBlurMask::BuildSqrGamma(fGamma, gammaScale);
        else
            SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale);
    }
#endif
    SkASSERT(radius >= 0);
    SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount);
    SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
}

SkMask::Format SkBlurMaskFilterImpl::getFormat() {
    return SkMask::kA8_Format;
}

bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
                                      const SkMatrix& matrix, SkIPoint* margin) {
    SkScalar radius;
    if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
        radius = fRadius;
    } else {
        radius = matrix.mapRadius(fRadius);
    }

    // To avoid unseemly allocation requests (esp. for finite platforms like
    // handset) we limit the radius so something manageable. (as opposed to
    // a request like 10,000)
    static const SkScalar MAX_RADIUS = SkIntToScalar(128);
    radius = SkMinScalar(radius, MAX_RADIUS);
    SkBlurMask::Quality blurQuality =
        (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
            SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality;

    return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
                            blurQuality, margin);
}

SkFlattenable* SkBlurMaskFilterImpl::CreateProc(SkFlattenableReadBuffer& buffer) {
    return SkNEW_ARGS(SkBlurMaskFilterImpl, (buffer));
}

SkFlattenable::Factory SkBlurMaskFilterImpl::getFactory() {
    return CreateProc;
}

SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer)
        : SkMaskFilter(buffer) {
    fRadius = buffer.readScalar();
    fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readS32();
    fBlurFlags = buffer.readU32() & SkBlurMaskFilter::kAll_BlurFlag;
    SkASSERT(fRadius >= 0);
    SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
}

void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) {
    this->INHERITED::flatten(buffer);
    buffer.writeScalar(fRadius);
    buffer.write32(fBlurStyle);
    buffer.write32(fBlurFlags);
}

static const SkMaskFilter::BlurType gBlurStyle2BlurType[] = {
    SkMaskFilter::kNormal_BlurType,
    SkMaskFilter::kSolid_BlurType,
    SkMaskFilter::kOuter_BlurType,
    SkMaskFilter::kInner_BlurType,
};

SkMaskFilter::BlurType SkBlurMaskFilterImpl::asABlur(BlurInfo* info) {
    if (info) {
        info->fRadius = fRadius;
        info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag);
        info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag);
    }
    return gBlurStyle2BlurType[fBlurStyle];
}

///////////////////////////////////////////////////////////////////////////////

static SkFlattenable::Registrar gReg("SkBlurMaskFilter",
                                     SkBlurMaskFilterImpl::CreateProc);

<|endoftext|>


<commit_before>#include "gurobi_solver.h"

#include <Eigen/Core>
#include "gurobi_c++.h"

#include "drake/solvers/Optimization.h"
#include "drake/common/drake_assert.h"

namespace drake {
namespace solvers {

bool GurobiSolver::available() const { return true; }

// TODO(naveenoid): This is currently largely copy-pasta from the deprecated
// Gurobi wrapper in solvers. Utilise sparsity in the constraint matrices,
// i.e. Something like :
//    Eigen::SparseMatrix<double, Eigen::RowMajor> sparseA(A.sparseView());
//    sparseA.makeCompressed();
//    error =  GRBaddconstrs(model, A.rows(), sparseA.nonZeros(),
//                           sparseA.InnerIndices(), sparseA.OuterStarts(),
//                           sparseA.Values(),sense, b.data(), NULL);
//    return(error);

template <typename DerivedA, typename DerivedB>
int AddConstraints(GRBmodel* model, Eigen::MatrixBase<DerivedA> const& A,
                    Eigen::MatrixBase<DerivedB> const& b, char sense,
                    double sparseness_threshold = 1e-8) {
  std::vector<int> cind(A.cols(), 0);
  std::vector<double> cval(A.cols(), 0.0);

  int error = 0;
  for (size_t i = 0; i < A.rows(); i++) {
    int nnz = 0;
    for (size_t j = 0; j < A.cols(); j++) {
      if (std::abs(A(i, j)) > sparseness_threshold) {
        cval[nnz] = A(i, j);
        cind[nnz++] = j;
      }
    }
    error += GRBaddconstr(model, nnz, &cind[0], &cval[0], sense, b(i), NULL);
    if (error) break;
  }
  return error;
}

// Splits out the quadratic costs and makes calls to add them individually.
int AddCosts(GRBmodel *model, OptimizationProblem& prog,
             double sparseness_threshold = 1e-8) {
  int error = 0;
  int num_constraint_vars = 0;
  int start_row = 0;
  for (const auto& binding : prog.quadratic_costs()) {
    const auto& c = binding.constraint();

    num_constraint_vars = binding.GetNumElements();

    Eigen::MatrixXd Q = 0.5 * (c->Q());
    Eigen::VectorXd b = c->b();

    // Check for square matrices.
    DRAKE_ASSERT(Q.rows() == Q.cols());
    // Check for symmetric matrices.
    DRAKE_ASSERT(Q.transpose() == Q);
    // Check for Quadratic and Linear Cost dimensions.
    DRAKE_ASSERT(Q.rows() == num_constraint_vars);
    DRAKE_ASSERT(b.cols() == 1);
    DRAKE_ASSERT(b.rows() == num_constraint_vars);

    double individual_quadratic_cost_value = 0.0;
    int row_ind = 0, col_ind = 0;

    // adding each Q term (only upper triangular).
    for (size_t i = 0; i < num_constraint_vars; i++) {
      for (size_t j = i; j < num_constraint_vars; j++) {
        if (std::abs(Q(i, j)) > sparseness_threshold) {
          row_ind = i + start_row;
          col_ind = j + start_row;
          // TODO(naveenoid) : Port to batch addition mode of this function
          // by utilising the Upper right (or lower left) triangular matrix.
          // The single element addition method used below is recommended
          // initially by Gurobi since it has a low cost.
          individual_quadratic_cost_value = Q(i, j);
          error += GRBaddqpterms(model, 1, &row_ind, &col_ind,
                        &individual_quadratic_cost_value);
          if (error) break;
        }
        if (error) break;
      }
      if (error) break;
    }
    error += GRBsetdblattrarray(model, "Obj", start_row,
                                num_constraint_vars, b.data());
    start_row = start_row + Q.rows();
    if (error) break;
  }
  return(error);
}
// Splits out the equality and inequality constraints and makes call to
// add any non-inf constraints.
int ProcessConstraints(GRBmodel *model, OptimizationProblem& prog,
                       double sparseness_threshold = 1e-8) {
  int error = 0;
  // TODO(naveenoid) : needs test coverage.
  for (const auto& binding : prog.linear_equality_constraints()) {
    const auto& c = binding.constraint();
    error += AddConstraints(model, c->A(), c->lower_bound(), GRB_EQUAL, 1e-18);
  }

  for (const auto& binding : prog.linear_constraints()) {
    const auto& c = binding.constraint();

    if (c->lower_bound() !=
        -Eigen::MatrixXd::Constant((c->lower_bound()).rows(), 1,
                                   std::numeric_limits<double>::infinity())) {
      error += AddConstraints(model, c->A(), c->lower_bound(),
                              GRB_GREATER_EQUAL, sparseness_threshold);
    }
    if (c->upper_bound() !=
        Eigen::MatrixXd::Constant((c->upper_bound()).rows(), 1,
                                  std::numeric_limits<double>::infinity())) {
      error += AddConstraints(model, c->A(), c->upper_bound(),
                              GRB_LESS_EQUAL, sparseness_threshold);
    }
  }
  return(error);
}

SolutionResult GurobiSolver::Solve(OptimizationProblem& prog) const {
  // We only process quadratic costs and linear / bounding box
  // constraints

  GRBenv* env = NULL;
  GRBloadenv(&env, NULL);
  // Corresponds to no console or file logging.
  GRBsetintparam(env, GRB_INT_PAR_OUTPUTFLAG, 0);

  DRAKE_ASSERT(prog.generic_costs().empty());
  DRAKE_ASSERT(prog.generic_constraints().empty());

  int num_vars = prog.num_vars();

  // bound constraints
  std::vector<double> xlow(num_vars, -std::numeric_limits<double>::infinity());
  std::vector<double> xupp(num_vars, std::numeric_limits<double>::infinity());

  for (const auto& binding : prog.bounding_box_constraints()) {
    const auto& c = binding.constraint();
    const Eigen::VectorXd& lower_bound = c->lower_bound();
    const Eigen::VectorXd& upper_bound = c->upper_bound();
    for (const DecisionVariableView& v : binding.variable_list()) {
      for (size_t k = 0; k < v.size(); k++) {
        const int idx = v.index() + k;
        xlow[idx] = std::max(lower_bound(k), xlow[idx]);
        xupp[idx] = std::min(upper_bound(k), xupp[idx]);
      }
    }
  }

  GRBmodel* model = NULL;
  GRBnewmodel(env, &model, "QP", num_vars, NULL, &xlow[0], &xupp[0], NULL,
              NULL);

  int error = 0;
  // TODO(naveenoid) : This needs access externally.
  double sparseness_threshold = 1e-14;
  error = AddCosts(model, prog, sparseness_threshold);
  error &= ProcessConstraints(model, prog, sparseness_threshold);

  SolutionResult result = SolutionResult::kSolutionFound;
  error = GRBoptimize(model);

  if (error) {
    // TODO(naveenoid) : log error message using GRBgeterrormsg(env)
    result = SolutionResult::kInvalidInput;
  } else {
    int optimstatus = 0;
    GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);

    if (optimstatus != GRB_OPTIMAL) {
      if (optimstatus == GRB_INF_OR_UNBD) {
        result = SolutionResult::kInfeasibleConstraints;
      } else {
        result = SolutionResult::kUnknownError;
      }
    }
  }

  Eigen::VectorXd sol_vector = Eigen::VectorXd::Zero(num_vars);

  GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, num_vars, sol_vector.data());
  prog.SetDecisionVariableValues(sol_vector);

  prog.SetSolverResult("Gurobi", 0);

  GRBfreemodel(model);
  GRBfreeenv(env);

  return result;
}

}  // namespace drake
}  // namespace solvers
<commit_msg>error processing and review comments addressed<commit_after>#include "gurobi_solver.h"

#include <Eigen/Core>
#include "gurobi_c++.h"

#include "drake/common/drake_assert.h"
#include "drake/solvers/Optimization.h"

namespace drake {
namespace solvers {
namespace {

// TODO(naveenoid): This is currently largely copy-pasta from the deprecated
// Gurobi wrapper in solvers. Utilise sparsity in the constraint matrices,
// i.e. Something like :
//    Eigen::SparseMatrix<double, Eigen::RowMajor> sparseA(A.sparseView());
//    sparseA.makeCompressed();
//    error =  GRBaddconstrs(model, A.rows(), sparseA.nonZeros(),
//                           sparseA.InnerIndices(), sparseA.OuterStarts(),
//                           sparseA.Values(),sense, b.data(), nullptr);
//    return(error);

template <typename DerivedA, typename DerivedB>
int AddConstraints(GRBmodel* model, Eigen::MatrixBase<DerivedA> const& A,
                   Eigen::MatrixBase<DerivedB> const& b, char sense,
                   double sparseness_threshold) {
  std::vector<int> cind(A.cols(), 0);
  std::vector<double> cval(A.cols(), 0.0);

  int error = 0;
  for (size_t i = 0; i < A.rows(); i++) {
    int nnz = 0;
    for (size_t j = 0; j < A.cols(); j++) {
      if (std::abs(A(i, j)) > sparseness_threshold) {
        cval[nnz] = A(i, j);
        cind[nnz++] = j;
      }
    }
    error = GRBaddconstr(model, nnz, &cind[0], &cval[0], sense, b(i), nullptr);
    if (error) break;
  }
  return error;
}

// Splits out the quadratic costs and makes calls to add them individually.
int AddCosts(GRBmodel* model, OptimizationProblem& prog,
             double sparseness_threshold) {
  int error = 0;
  int num_constraint_vars = 0;
  int start_row = 0;
  for (const auto& binding : prog.quadratic_costs()) {
    const auto& c = binding.constraint();

    num_constraint_vars = binding.GetNumElements();

    Eigen::MatrixXd Q = 0.5 * (c->Q());
    Eigen::VectorXd b = c->b();

    // Check for square matrices.
    DRAKE_ASSERT(Q.rows() == Q.cols());
    // Check for symmetric matrices.
    DRAKE_ASSERT(Q.transpose() == Q);
    // Check for Quadratic and Linear Cost dimensions.
    DRAKE_ASSERT(Q.rows() == num_constraint_vars);
    DRAKE_ASSERT(b.cols() == 1);
    DRAKE_ASSERT(b.rows() == num_constraint_vars);

    double individual_quadratic_cost_value = 0.0;
    int row_ind = 0, col_ind = 0;

    // adding each Q term (only upper triangular).
    for (size_t i = 0; i < num_constraint_vars; i++) {
      for (size_t j = i; j < num_constraint_vars; j++) {
        if (std::abs(Q(i, j)) > sparseness_threshold) {
          row_ind = i + start_row;
          col_ind = j + start_row;
          // TODO(naveenoid) : Port to batch addition mode of this function
          // by utilising the Upper right (or lower left) triangular matrix.
          // The single element addition method used below is recommended
          // initially by Gurobi since it has a low cost.
          individual_quadratic_cost_value = Q(i, j);
          error = GRBaddqpterms(model, 1, &row_ind, &col_ind,
                                &individual_quadratic_cost_value);
          if (error) {
            return (error);
          }
        }
      }
    }
    error = GRBsetdblattrarray(model, "Obj", start_row, num_constraint_vars,
                               b.data());
    start_row = start_row + Q.rows();
    if (error) {
      return error;
    }
  }
  return error;
}
// Splits out the equality and inequality constraints and makes call to
// add any non-inf constraints.
int ProcessConstraints(GRBmodel* model, OptimizationProblem& prog,
                       double sparseness_threshold) {
  int error = 0;
  // TODO(naveenoid) : needs test coverage.
  for (const auto& binding : prog.linear_equality_constraints()) {
    const auto& c = binding.constraint();
    error = AddConstraints(model, c->A(), c->lower_bound(), GRB_EQUAL,
                           sparseness_threshold);
    if (error) {
      return error;
    }
  }

  for (const auto& binding : prog.linear_constraints()) {
    const auto& c = binding.constraint();

    if (c->lower_bound() !=
        -Eigen::MatrixXd::Constant((c->lower_bound()).rows(), 1,
                                   std::numeric_limits<double>::infinity())) {
      error = AddConstraints(model, c->A(), c->lower_bound(), GRB_GREATER_EQUAL,
                             sparseness_threshold);
      if (error) {
        return error;
      }
    }
    if (c->upper_bound() !=
        Eigen::MatrixXd::Constant((c->upper_bound()).rows(), 1,
                                  std::numeric_limits<double>::infinity())) {
      error = AddConstraints(model, c->A(), c->upper_bound(), GRB_LESS_EQUAL,
                             sparseness_threshold);
      if (error) {
        return error;
      }
    }
  }
  return error;
}
}  // close namespace

bool GurobiSolver::available() const { return true; }

SolutionResult GurobiSolver::Solve(OptimizationProblem& prog) const {
  // We only process quadratic costs and linear / bounding box
  // constraints

  GRBenv* env = nullptr;
  GRBloadenv(&env, nullptr);
  // Corresponds to no console or file logging.
  GRBsetintparam(env, GRB_INT_PAR_OUTPUTFLAG, 0);

  DRAKE_ASSERT(prog.generic_costs().empty());
  DRAKE_ASSERT(prog.generic_constraints().empty());

  int num_vars = prog.num_vars();

  // bound constraints
  std::vector<double> xlow(num_vars, -std::numeric_limits<double>::infinity());
  std::vector<double> xupp(num_vars, std::numeric_limits<double>::infinity());

  for (const auto& binding : prog.bounding_box_constraints()) {
    const auto& c = binding.constraint();
    const Eigen::VectorXd& lower_bound = c->lower_bound();
    const Eigen::VectorXd& upper_bound = c->upper_bound();
    for (const DecisionVariableView& v : binding.variable_list()) {
      for (size_t k = 0; k < v.size(); k++) {
        const int idx = v.index() + k;
        xlow[idx] = std::max(lower_bound(k), xlow[idx]);
        xupp[idx] = std::min(upper_bound(k), xupp[idx]);
      }
    }
  }

  GRBmodel* model = nullptr;
  GRBnewmodel(env, &model, "QP", num_vars, nullptr, &xlow[0], &xupp[0], nullptr,
              nullptr);

  int error = 0;
  // TODO(naveenoid) : This needs access externally.
  double sparseness_threshold = 1e-14;
  error = AddCosts(model, prog, sparseness_threshold);
  if (!error) {
    error = ProcessConstraints(model, prog, sparseness_threshold);
  }

  SolutionResult result = SolutionResult::kSolutionFound;

  if (!error) {
    error = GRBoptimize(model);
  }

  // If any error exists so far, its either from invalid input or
  // from unknown errors.
  // TODO(naveenoid) : Properly handle gurobi specific error.
  // message.
  if (error) {
    // TODO(naveenoid) : log error message using GRBgeterrormsg(env).
    result = SolutionResult::kInvalidInput;
  } else {
    int optimstatus = 0;
    GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);

    if (optimstatus != GRB_OPTIMAL) {
      if (optimstatus == GRB_INF_OR_UNBD) {
        result = SolutionResult::kInfeasibleConstraints;
      } else {
        result = SolutionResult::kUnknownError;
      }
    }
  }

  Eigen::VectorXd sol_vector = Eigen::VectorXd::Zero(num_vars);

  GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, num_vars, sol_vector.data());
  prog.SetDecisionVariableValues(sol_vector);

  prog.SetSolverResult("Gurobi", 0);

  GRBfreemodel(model);
  GRBfreeenv(env);

  return result;
}

}  // namespace drake
}  // namespace solvers
<|endoftext|>


<commit_before><commit_msg>Read file values from the correct properties.<commit_after><|endoftext|>


<commit_before>/**
 *  Play takes one robot and drives it in a precomputed path
 */

#include <iostream>
#include "TestRectMotionControl.hpp"
#include "math.h"

using namespace std;
using namespace Geometry2d;

Gameplay::Plays::TestRectMotionControl::TestRectMotionControl(GameplayModule *gameplay):
	Play(gameplay, 1),
	fsm_state_(Track),
	hWidth_(1.0),
	hHeight_(0.5),
	waitFramesMax_(75),
	pathGoalIdx_(0),
	angleGoalIdx_(0)
{
	// find the center of our side
	Point center(0.0, Constants::Field::Length/4);

	Point p1(center.x+hWidth_, center.y+hHeight_);
	Point p2(center.x-hWidth_, center.y+hHeight_);
	Point p3(center.x-hWidth_, center.y-hHeight_);
	Point p4(center.x+hWidth_, center.y-hHeight_);

	path_.push_back(p1);
	path_.push_back(p2);
	path_.push_back(p3);
	path_.push_back(p4);

	angles_.push_back(0*M_PI/180);
	angles_.push_back(45*M_PI/180);
	angles_.push_back((90+60)*M_PI/180);
}

bool Gameplay::Plays::TestRectMotionControl::applicable()
{
	bool refApplicable =_gameplay->state()->gameState.playing();
	return refApplicable;
}

bool Gameplay::Plays::TestRectMotionControl::assign(set<Robot *> &available)
{
	takeBest(available);
	return _robots.size() >= _minRobots;
}

bool Gameplay::Plays::TestRectMotionControl::run()
{
	// pull out the robot pose
	Point pos = robot()->pos();

	int pathGoalThisIdx = pathGoalIdx_;
	int pathGoalNextIdx = (pathGoalIdx_ + 1) % ((int)path_.size());

	int angleGoalThisIdx = angleGoalIdx_;
	int angleGoalNextIdx = (angleGoalIdx_ + 1) % ((int)angles_.size());

	Point goal = path_.at(pathGoalThisIdx);

	float angleGoal = angles_.at(angleGoalThisIdx);

	// check whether to setup a particular point or run a path
	path_t path;
	if (fsm_state_ == Wait)
	{
		if(waitFrames_-- <= 0)
		{
			// go to next state
			pathGoalIdx_ = pathGoalNextIdx;
			goal = path_.at(pathGoalIdx_);
			fsm_state_ = Track;

			if(pathGoalIdx_ == 0){ // change angle
				angleGoalIdx_ = angleGoalNextIdx;
				angleGoal = angles_.at(angleGoalIdx_);
			}
		}
	}
	else if (fsm_state_ == Track)
	{
		float thresh = 0.1;
		if (pos.distTo(goal) <= thresh)
		{
			fsm_state_ = Wait;
			waitFrames_ = waitFramesMax_;
		}
	}

	// issue the turn command
	Point angleGoalPt(cos(angleGoal),sin(angleGoal));
	angleGoalPt *= 10;
	angleGoalPt += robot()->pos();
	robot()->face(angleGoalPt,false);

	// issue the motion command
	robot()->move(goal, true);

	return true;
}
<commit_msg>Fixed rect motion control test to add angle mode that faces the dir. of travel.<commit_after>/**
 *  Play takes one robot and drives it in a precomputed path
 */

#include <iostream>
#include "TestRectMotionControl.hpp"
#include "math.h"

using namespace std;
using namespace Geometry2d;

Gameplay::Plays::TestRectMotionControl::TestRectMotionControl(GameplayModule *gameplay):
	Play(gameplay, 1),
	fsm_state_(Track),
	hWidth_(1.0),
	hHeight_(0.5),
	waitFramesMax_(75),
	pathGoalIdx_(0),
	angleGoalIdx_(0)
{
	// find the center of our side
	Point center(0.0, Constants::Field::Length/4);

	Point p1(center.x+hWidth_, center.y+hHeight_);
	Point p2(center.x-hWidth_, center.y+hHeight_);
	Point p3(center.x-hWidth_, center.y-hHeight_);
	Point p4(center.x+hWidth_, center.y-hHeight_);

	path_.push_back(p1);
	path_.push_back(p2);
	path_.push_back(p3);
	path_.push_back(p4);

	angles_.push_back(-1); // negative values will point in direction of travel
	angles_.push_back(0*M_PI/180);
	angles_.push_back(45*M_PI/180);
	angles_.push_back((90+60)*M_PI/180);
}

bool Gameplay::Plays::TestRectMotionControl::applicable()
{
	bool refApplicable =_gameplay->state()->gameState.playing();
	return refApplicable;
}

bool Gameplay::Plays::TestRectMotionControl::assign(set<Robot *> &available)
{
	takeBest(available);
	return _robots.size() >= _minRobots;
}

bool Gameplay::Plays::TestRectMotionControl::run()
{
	// pull out the robot pose
	Point pos = robot()->pos();

	int pathGoalThisIdx = pathGoalIdx_;
	int pathGoalNextIdx = (pathGoalIdx_ + 1) % ((int)path_.size());

	int angleGoalThisIdx = angleGoalIdx_;
	int angleGoalNextIdx = (angleGoalIdx_ + 1) % ((int)angles_.size());

	Point goal = path_.at(pathGoalThisIdx);

	float angleGoal = angles_.at(angleGoalThisIdx);

	// check whether to setup a particular point or run a path
	path_t path;
	if (fsm_state_ == Wait)
	{
		if(waitFrames_-- <= 0)
		{
			// go to next state
			pathGoalIdx_ = pathGoalNextIdx;
			goal = path_.at(pathGoalIdx_);
			fsm_state_ = Track;

			if(pathGoalIdx_ == 0){ // change angle
				angleGoalIdx_ = angleGoalNextIdx;
				angleGoal = angles_.at(angleGoalIdx_);
			}
		}
	}
	else if (fsm_state_ == Track)
	{
		float thresh = 0.1;
		if (pos.distTo(goal) <= thresh)
		{
			fsm_state_ = Wait;
			waitFrames_ = waitFramesMax_;
		}
	}

	// issue the turn command
	if(angleGoal >= 0) // point at direction of angle we chose
	{
		Point angleGoalPt(cos(angleGoal),sin(angleGoal));
		angleGoalPt *= 10;
		angleGoalPt += robot()->pos();
		robot()->face(angleGoalPt,false);
	}else{ // point in direction of travel
		Point prevGoal = path_.at((pathGoalIdx_ - 1 + (int)path_.size()) % ((int)path_.size()));
		Point angleVec = goal - prevGoal;
		Point angleGoalPt(angleVec + goal);
		robot()->face(angleGoalPt,false);
	}

	// issue the motion command
	robot()->move(goal, true);

	return true;
}
<|endoftext|>


<commit_before>
#include "useravatarimageprovider.h"

static QImage fallbackImage()
{
    QImage fallback;
    fallback.load("pics/qtlogo.png");
//    *realSize = fallback.size();
    return fallback;
}

void UserAvatarImageResponse::loadImage()
{
    QImage image;
    bool loadResult = image.loadFromData(m_pImgCtrl->downloadedData());
    if (!loadResult || image.isNull()) image = fallbackImage();

    m_texture = QQuickTextureFactory::textureFactoryForImage(image);

    emit finished();
}

UserAvatarImageResponse::UserAvatarImageResponse(const QString& id, const QSize& requestedSize, BankiRuForum::Image& avatarInfo):
    m_id(id), m_requestedSize(requestedSize), m_avatarInfo(avatarInfo), m_texture(nullptr), m_cancelled(false)
{
    setAutoDelete(false);
}

QQuickTextureFactory* UserAvatarImageResponse::textureFactory() const
{
    return m_texture;
}

void UserAvatarImageResponse::run()
{
    if (m_cancelled)
    {
        qDebug() << "Running cancelled user avatar:" << m_id;
        emit finished();
        return;
    }

    qDebug() << "Running user avatar" << m_id;

    m_pImgCtrl = new FileDownloader( QUrl( "https://upload.wikimedia.org/wikipedia/en/5/5a/Qt_Creator_logo.png" ) /*m_avatarInfo.m_url*/, NULL /*this*/);
    //connect(m_pImgCtrl, SIGNAL(downloaded()), this, SLOT(loadImage()));
}

void UserAvatarImageResponse::cancel()
{
    m_cancelled = true;
    qDebug() << "CANCEL ALBUM ART" << m_id;
}

// FIXME: implement
//virtual QString UserAvatarImageResponse::errorString() const;

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

UserAvatarAsyncImageProvider::UserAvatarAsyncImageProvider(BankiRuForum::UserPosts userPosts) : m_userPosts( userPosts )
{
}

QQuickImageResponse* UserAvatarAsyncImageProvider::requestImageResponse(const QString& id, const QSize& requestedSize)
{
    qDebug() << "Loading user avatar image" << id;

    // Search for user with specified name
    BankiRuForum::Image avatarInfo;
    for( int i = 0; i < m_userPosts.size(); ++i )
    {
        auto currentUser = m_userPosts[i].first;
        if( QString::compare( currentUser.m_userName, id, Qt::CaseInsensitive ) == 0 )
        {
            qDebug() << "Avatar info for user" << id << "was found successfully";
            avatarInfo = currentUser.m_userAvatar;
            break;
        }
    }

    // FIXME: should it be started MANUALLY?
    UserAvatarImageResponse* response = new UserAvatarImageResponse(id, requestedSize, avatarInfo);
    QThreadPool::globalInstance()->start( response );
    return response;
}

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

UserAvatarImageProvider::UserAvatarImageProvider(BankiRuForum::UserPosts userPosts) : QQuickImageProvider(QQuickImageProvider::Pixmap), m_userPosts(userPosts)
{
}

QPixmap UserAvatarImageProvider::requestPixmap(const QString& id, QSize* size, const QSize& requestedSize)
{
    BankiRuForum::Image imgAvatar = m_userPosts[m_idxCurrentUser].first.m_userAvatar;
    if (size)
    {
        *size = QSize(imgAvatar.m_width, imgAvatar.m_height);
    }

    // FIXME: use real avatar id
    QUrl imageUrl("https://upload.wikimedia.org/wikipedia/en/5/5a/Qt_Creator_logo.png");
    m_pImgCtrl = new FileDownloader(imageUrl, this);

//    connect(m_pImgCtrl, SIGNAL(downloaded()), this, SLOT(loadImage()));

    if (requestedSize.width() > 0 && requestedSize.height())
        m_pxmUserAvatar = m_pxmUserAvatar.scaled(requestedSize);
    return m_pxmUserAvatar;
}
<commit_msg>Small compiler warning fix<commit_after>
#include "useravatarimageprovider.h"

static QImage fallbackImage()
{
    QImage fallback;
    fallback.load("pics/qtlogo.png");
//    *realSize = fallback.size();
    return fallback;
}

void UserAvatarImageResponse::loadImage()
{
    QImage image;
    bool loadResult = image.loadFromData(m_pImgCtrl->downloadedData());
    if (!loadResult || image.isNull()) image = fallbackImage();

    m_texture = QQuickTextureFactory::textureFactoryForImage(image);

    emit finished();
}

UserAvatarImageResponse::UserAvatarImageResponse(const QString& id, const QSize& requestedSize, BankiRuForum::Image& avatarInfo):
    m_id(id), m_requestedSize(requestedSize), m_avatarInfo(avatarInfo), m_texture(nullptr), m_cancelled(false)
{
    setAutoDelete(false);
}

QQuickTextureFactory* UserAvatarImageResponse::textureFactory() const
{
    return m_texture;
}

void UserAvatarImageResponse::run()
{
    if (m_cancelled)
    {
        qDebug() << "Running cancelled user avatar:" << m_id;
        emit finished();
        return;
    }

    qDebug() << "Running user avatar" << m_id;

    m_pImgCtrl = new FileDownloader( QUrl( "https://upload.wikimedia.org/wikipedia/en/5/5a/Qt_Creator_logo.png" ) /*m_avatarInfo.m_url*/, NULL /*this*/);
    //connect(m_pImgCtrl, SIGNAL(downloaded()), this, SLOT(loadImage()));
}

void UserAvatarImageResponse::cancel()
{
    m_cancelled = true;
    qDebug() << "CANCEL ALBUM ART" << m_id;
}

// FIXME: implement
//virtual QString UserAvatarImageResponse::errorString() const;

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

UserAvatarAsyncImageProvider::UserAvatarAsyncImageProvider(BankiRuForum::UserPosts userPosts) : m_userPosts( userPosts )
{
}

QQuickImageResponse* UserAvatarAsyncImageProvider::requestImageResponse(const QString& id, const QSize& requestedSize)
{
    qDebug() << "Loading user avatar image" << id;

    // Search for user with specified name
    BankiRuForum::Image avatarInfo;
    for( int i = 0; i < m_userPosts.size(); ++i )
    {
        auto currentUser = m_userPosts[i].first;
        if( QString::compare( currentUser.m_userName, id, Qt::CaseInsensitive ) == 0 )
        {
            qDebug() << "Avatar info for user" << id << "was found successfully";
            avatarInfo = currentUser.m_userAvatar;
            break;
        }
    }

    // FIXME: should it be started MANUALLY?
    UserAvatarImageResponse* response = new UserAvatarImageResponse(id, requestedSize, avatarInfo);
    QThreadPool::globalInstance()->start( response );
    return response;
}

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

UserAvatarImageProvider::UserAvatarImageProvider(BankiRuForum::UserPosts userPosts) : QQuickImageProvider(QQuickImageProvider::Pixmap), m_userPosts(userPosts)
{
}

QPixmap UserAvatarImageProvider::requestPixmap(const QString& id, QSize* size, const QSize& requestedSize)
{
    Q_UNUSED(id);

    BankiRuForum::Image imgAvatar = m_userPosts[m_idxCurrentUser].first.m_userAvatar;
    if (size)
    {
        *size = QSize(imgAvatar.m_width, imgAvatar.m_height);
    }

    // FIXME: use real avatar id
    QUrl imageUrl("https://upload.wikimedia.org/wikipedia/en/5/5a/Qt_Creator_logo.png");
    m_pImgCtrl = new FileDownloader(imageUrl, this);

//    connect(m_pImgCtrl, SIGNAL(downloaded()), this, SLOT(loadImage()));

    if (requestedSize.width() > 0 && requestedSize.height())
        m_pxmUserAvatar = m_pxmUserAvatar.scaled(requestedSize);
    return m_pxmUserAvatar;
}
<|endoftext|>


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

#ifdef _OPENGL
#include <hltypes/hplatform.h>

#ifdef __APPLE__
	#include <TargetConditionals.h>
#endif
#if TARGET_OS_IPHONE
	#include <OpenGLES/ES1/gl.h>
	#include <OpenGLES/ES1/glext.h>
#elif _OPENGLES
	#include <GLES/gl.h>
#else
	#ifndef __APPLE__
		#include <gl/GL.h>
	#else
		#include <OpenGL/gl.h>
	#endif
#endif

#include <hltypes/hlog.h>
#include <hltypes/hstring.h>

#include "april.h"
#include "Image.h"
#include "OpenGL_RenderSystem.h"
#include "OpenGL_State.h"
#include "OpenGL_Texture.h"

#define APRIL_OGL_RENDERSYS ((OpenGL_RenderSystem*)april::rendersys)

namespace april
{
	OpenGL_Texture::OpenGL_Texture(bool fromResource) : Texture(fromResource), textureId(0), glFormat(0), internalFormat(0)
	{
	}

	bool OpenGL_Texture::_createInternalTexture(unsigned char* data, int size, Type type)
	{
		glGenTextures(1, &this->textureId);
		if (this->textureId == 0)
		{
			return false;
		}
		this->firstUpload = true;
		this->_setCurrentTexture();
		// required first call of glTexImage2D() to prevent problems
#if TARGET_OS_IPHONE
		if (this->dataFormat == GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG || this->dataFormat == GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG)
		{
			glCompressedTexImage2D(GL_TEXTURE_2D, 0, this->dataFormat, this->width, this->height, 0, size, data);
			this->firstUpload = false;
		}
#endif
		return true;
	}

	void OpenGL_Texture::_assignFormat()
	{
		switch (this->format)
		{
		case Image::FORMAT_ARGB:
		case Image::FORMAT_XRGB:
		case Image::FORMAT_RGBA:
		case Image::FORMAT_RGBX:
		case Image::FORMAT_ABGR:
		case Image::FORMAT_XBGR:
			this->glFormat = this->internalFormat = GL_RGBA;
			break;
		// for optimizations
		case Image::FORMAT_BGRA:
		case Image::FORMAT_BGRX:
#if !defined(_ANDROID) && !defined(_WIN32)
#ifndef __APPLE__
			this->glFormat = GL_BGRA;
#else
			this->glFormat = GL_BGRA_EXT;
#endif
#else
			this->glFormat = GL_RGBA;
#endif
			this->internalFormat = GL_RGBA;
			break;
		case Image::FORMAT_RGB:
			this->glFormat = this->internalFormat = GL_RGB;
			break;
		case Image::FORMAT_BGR:
#if !defined(_ANDROID) && !defined(_WIN32)
#ifndef __APPLE__
			this->glFormat = GL_BGR;
#else
			this->glFormat = GL_BGRA_EXT; // iOS doesn't accept BGR. this option hasn't been tested since the last refactor
#endif
#else
			this->glFormat = GL_RGB;
#endif
			this->internalFormat = GL_RGB;
			break;
		case Image::FORMAT_ALPHA:
			this->glFormat = this->internalFormat = GL_ALPHA;
			break;
		case Image::FORMAT_GRAYSCALE:
			this->glFormat = this->internalFormat = GL_LUMINANCE;
			break;
		case Image::FORMAT_PALETTE: // TODOaa - does palette use RGBA?
			this->glFormat = this->internalFormat = GL_RGBA;
			break;
		default:
			this->glFormat = this->internalFormat = GL_RGBA;
			break;
		}
	}

	OpenGL_Texture::~OpenGL_Texture()
	{
		this->unload();
		this->waitForAsyncLoad();
	}

	void OpenGL_Texture::_setCurrentTexture()
	{
		APRIL_OGL_RENDERSYS->currentState.textureId = APRIL_OGL_RENDERSYS->deviceState.textureId = this->textureId;
		glBindTexture(GL_TEXTURE_2D, this->textureId);
		APRIL_OGL_RENDERSYS->currentState.textureFilter = APRIL_OGL_RENDERSYS->deviceState.textureFilter = this->filter;
		APRIL_OGL_RENDERSYS->_setTextureFilter(this->filter);
		APRIL_OGL_RENDERSYS->currentState.textureAddressMode = APRIL_OGL_RENDERSYS->deviceState.textureAddressMode = this->addressMode;
		APRIL_OGL_RENDERSYS->_setTextureAddressMode(this->addressMode);
	}

	bool OpenGL_Texture::isLoaded()
	{
		return (this->textureId != 0);
	}

	void OpenGL_Texture::unload()
	{
		Texture::unload();
		if (this->textureId != 0)
		{
			hlog::write(april::logTag, "Unloading texture: " + this->_getInternalName());
			glDeleteTextures(1, &this->textureId);
			this->textureId = 0;
		}
	}

	Texture::Lock OpenGL_Texture::_tryLockSystem(int x, int y, int w, int h)
	{
		Lock lock;
		Image::Format nativeFormat = april::rendersys->getNativeTextureFormat(this->format);
		int gpuBpp = Image::getFormatBpp(nativeFormat);
		lock.activateLock(0, 0, w, h, x, y, new unsigned char[w * h * gpuBpp], w, h, nativeFormat);
		lock.systemBuffer = lock.data;
		return lock;
	}

	bool OpenGL_Texture::_unlockSystem(Lock& lock, bool update)
	{
		if (lock.systemBuffer == NULL)
		{
			return false;
		}
		if (update)
		{
			if (this->format != Image::FORMAT_PALETTE)
			{
				this->_setCurrentTexture();
				if (this->width == lock.w && this->height == lock.h)
				{
					this->_uploadPotSafeData(lock.data);
				}
				else
				{
					if (this->firstUpload)
					{
						this->_uploadPotSafeClearData();
					}
					glTexSubImage2D(GL_TEXTURE_2D, 0, lock.dx, lock.dy, lock.w, lock.h, this->glFormat, GL_UNSIGNED_BYTE, lock.data);
				}
			}
			delete [] lock.data;
			this->firstUpload = false;
		}
		return update;
	}

	void OpenGL_Texture::_uploadPotSafeData(unsigned char* data)
	{
		glTexImage2D(GL_TEXTURE_2D, 0, this->internalFormat, this->width, this->height, 0, this->glFormat, GL_UNSIGNED_BYTE, data);
		RenderSystem::Caps caps = april::rendersys->getCaps();
		if (glGetError() == GL_INVALID_VALUE && !caps.npotTexturesLimited && !caps.npotTextures)
		{
			int w = this->width;
			int h = this->height;
			unsigned char* newData = this->_createPotData(w, h, data);
			glTexImage2D(GL_TEXTURE_2D, 0, this->internalFormat, w, h, 0, this->glFormat, GL_UNSIGNED_BYTE, newData);
			delete[] newData;
		}
	}

	void OpenGL_Texture::_uploadPotSafeClearData()
	{
		int size = this->getByteSize();
		unsigned char* clearColor = new unsigned char[size];
		memset(clearColor, 0, size);
		glTexImage2D(GL_TEXTURE_2D, 0, this->internalFormat, this->width, this->height, 0, this->glFormat, GL_UNSIGNED_BYTE, clearColor);
		delete[] clearColor;
		RenderSystem::Caps caps = april::rendersys->getCaps();
		if (glGetError() == GL_INVALID_VALUE && !caps.npotTexturesLimited && !caps.npotTextures)
		{
			int w = this->width;
			int h = this->height;
			clearColor = this->_createPotClearData(w, h); // can create POT sized data
			glTexImage2D(GL_TEXTURE_2D, 0, this->internalFormat, this->width, this->height, 0, this->glFormat, GL_UNSIGNED_BYTE, clearColor);
			delete[] clearColor;
		}
	}

	bool OpenGL_Texture::_uploadToGpu(int sx, int sy, int sw, int sh, int dx, int dy, unsigned char* srcData, int srcWidth, int srcHeight, Image::Format srcFormat)
	{
		if (this->format == Image::FORMAT_PALETTE)
		{
			return false;
		}
		this->load();
		this->_setCurrentTexture();
		if (sx == 0 && dx == 0 && sy == 0 && dy == 0 && sw == this->width && srcWidth == this->width && sh == this->height && srcHeight == this->height)
		{
			this->_uploadPotSafeData(srcData);
		}
		else
		{
			if (this->firstUpload)
			{
				this->_uploadPotSafeClearData();
			}
			int srcBpp = Image::getFormatBpp(srcFormat);
			if (sx == 0 && dx == 0 && srcWidth == this->width && sw == this->width)
			{
				glTexSubImage2D(GL_TEXTURE_2D, 0, dx, dy, sw, sh, this->glFormat, GL_UNSIGNED_BYTE, &srcData[(sx + sy * srcWidth) * srcBpp]);
			}
			else
			{
				for_iter (j, 0, sh)
				{
					glTexSubImage2D(GL_TEXTURE_2D, 0, dx, (dy + j), sw, 1, this->glFormat, GL_UNSIGNED_BYTE, &srcData[(sx + (sy + j) * srcWidth) * srcBpp]);
				}
			}
		}
		this->firstUpload = false;
		return true;
	}

}
#endif
<commit_msg>- added memory warning when GL texture data could not be uploaded<commit_after>/// @file
/// @version 3.5
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#ifdef _OPENGL
#include <hltypes/hplatform.h>

#ifdef __APPLE__
	#include <TargetConditionals.h>
#endif
#if TARGET_OS_IPHONE
	#include <OpenGLES/ES1/gl.h>
	#include <OpenGLES/ES1/glext.h>
#elif _OPENGLES
	#include <GLES/gl.h>
#else
	#ifndef __APPLE__
		#include <gl/GL.h>
	#else
		#include <OpenGL/gl.h>
	#endif
#endif

#include <hltypes/hlog.h>
#include <hltypes/hstring.h>

#include "april.h"
#include "Image.h"
#include "OpenGL_RenderSystem.h"
#include "OpenGL_State.h"
#include "OpenGL_Texture.h"

#define APRIL_OGL_RENDERSYS ((OpenGL_RenderSystem*)april::rendersys)

#define SAFE_TEXTURE_UPLOAD_CHECK(glError, call) \
	if (glError == GL_OUT_OF_MEMORY) \
	{ \
		if (!_preventRecursion) \
		{ \
			_preventRecursion = true; \
			april::window->handleLowMemoryWarning(); \
			_preventRecursion = false; \
			call; \
			glError = glGetError(); \
		} \
		if (glError == GL_OUT_OF_MEMORY) \
		{ \
			hlog::error(april::logTag, "Failed to upload texture data: Not enough VRAM!"); \
		} \
	}

namespace april
{
	static bool _preventRecursion = false;

	OpenGL_Texture::OpenGL_Texture(bool fromResource) : Texture(fromResource), textureId(0), glFormat(0), internalFormat(0)
	{
	}

	bool OpenGL_Texture::_createInternalTexture(unsigned char* data, int size, Type type)
	{
		glGenTextures(1, &this->textureId);
		if (this->textureId == 0)
		{
			return false;
		}
		this->firstUpload = true;
		this->_setCurrentTexture();
		// required first call of glTexImage2D() to prevent problems
#if TARGET_OS_IPHONE
		if (this->dataFormat == GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG || this->dataFormat == GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG)
		{
			glCompressedTexImage2D(GL_TEXTURE_2D, 0, this->dataFormat, this->width, this->height, 0, size, data);
			GLenum glError = glGetError();
			SAFE_TEXTURE_UPLOAD_CHECK(glError, glCompressedTexImage2D(GL_TEXTURE_2D, 0, this->dataFormat, this->width, this->height, 0, size, data));
			this->firstUpload = false;
		}
#endif
		return true;
	}

	void OpenGL_Texture::_assignFormat()
	{
		switch (this->format)
		{
		case Image::FORMAT_ARGB:
		case Image::FORMAT_XRGB:
		case Image::FORMAT_RGBA:
		case Image::FORMAT_RGBX:
		case Image::FORMAT_ABGR:
		case Image::FORMAT_XBGR:
			this->glFormat = this->internalFormat = GL_RGBA;
			break;
		// for optimizations
		case Image::FORMAT_BGRA:
		case Image::FORMAT_BGRX:
#if !defined(_ANDROID) && !defined(_WIN32)
#ifndef __APPLE__
			this->glFormat = GL_BGRA;
#else
			this->glFormat = GL_BGRA_EXT;
#endif
#else
			this->glFormat = GL_RGBA;
#endif
			this->internalFormat = GL_RGBA;
			break;
		case Image::FORMAT_RGB:
			this->glFormat = this->internalFormat = GL_RGB;
			break;
		case Image::FORMAT_BGR:
#if !defined(_ANDROID) && !defined(_WIN32)
#ifndef __APPLE__
			this->glFormat = GL_BGR;
#else
			this->glFormat = GL_BGRA_EXT; // iOS doesn't accept BGR. this option hasn't been tested since the last refactor
#endif
#else
			this->glFormat = GL_RGB;
#endif
			this->internalFormat = GL_RGB;
			break;
		case Image::FORMAT_ALPHA:
			this->glFormat = this->internalFormat = GL_ALPHA;
			break;
		case Image::FORMAT_GRAYSCALE:
			this->glFormat = this->internalFormat = GL_LUMINANCE;
			break;
		case Image::FORMAT_PALETTE: // TODOaa - does palette use RGBA?
			this->glFormat = this->internalFormat = GL_RGBA;
			break;
		default:
			this->glFormat = this->internalFormat = GL_RGBA;
			break;
		}
	}

	OpenGL_Texture::~OpenGL_Texture()
	{
		this->unload();
		this->waitForAsyncLoad();
	}

	void OpenGL_Texture::_setCurrentTexture()
	{
		APRIL_OGL_RENDERSYS->currentState.textureId = APRIL_OGL_RENDERSYS->deviceState.textureId = this->textureId;
		glBindTexture(GL_TEXTURE_2D, this->textureId);
		APRIL_OGL_RENDERSYS->currentState.textureFilter = APRIL_OGL_RENDERSYS->deviceState.textureFilter = this->filter;
		APRIL_OGL_RENDERSYS->_setTextureFilter(this->filter);
		APRIL_OGL_RENDERSYS->currentState.textureAddressMode = APRIL_OGL_RENDERSYS->deviceState.textureAddressMode = this->addressMode;
		APRIL_OGL_RENDERSYS->_setTextureAddressMode(this->addressMode);
	}

	bool OpenGL_Texture::isLoaded()
	{
		return (this->textureId != 0);
	}

	void OpenGL_Texture::unload()
	{
		Texture::unload();
		if (this->textureId != 0)
		{
			hlog::write(april::logTag, "Unloading texture: " + this->_getInternalName());
			glDeleteTextures(1, &this->textureId);
			this->textureId = 0;
		}
	}

	Texture::Lock OpenGL_Texture::_tryLockSystem(int x, int y, int w, int h)
	{
		Lock lock;
		Image::Format nativeFormat = april::rendersys->getNativeTextureFormat(this->format);
		int gpuBpp = Image::getFormatBpp(nativeFormat);
		lock.activateLock(0, 0, w, h, x, y, new unsigned char[w * h * gpuBpp], w, h, nativeFormat);
		lock.systemBuffer = lock.data;
		return lock;
	}

	bool OpenGL_Texture::_unlockSystem(Lock& lock, bool update)
	{
		if (lock.systemBuffer == NULL)
		{
			return false;
		}
		if (update)
		{
			if (this->format != Image::FORMAT_PALETTE)
			{
				this->_setCurrentTexture();
				if (this->width == lock.w && this->height == lock.h)
				{
					this->_uploadPotSafeData(lock.data);
				}
				else
				{
					if (this->firstUpload)
					{
						this->_uploadPotSafeClearData();
					}
					glTexSubImage2D(GL_TEXTURE_2D, 0, lock.dx, lock.dy, lock.w, lock.h, this->glFormat, GL_UNSIGNED_BYTE, lock.data);
				}
			}
			delete [] lock.data;
			this->firstUpload = false;
		}
		return update;
	}

	void OpenGL_Texture::_uploadPotSafeData(unsigned char* data)
	{
		glTexImage2D(GL_TEXTURE_2D, 0, this->internalFormat, this->width, this->height, 0, this->glFormat, GL_UNSIGNED_BYTE, data);
		GLenum glError = glGetError();
		SAFE_TEXTURE_UPLOAD_CHECK(glError, glTexImage2D(GL_TEXTURE_2D, 0, this->internalFormat, this->width, this->height, 0, this->glFormat, GL_UNSIGNED_BYTE, data));
		RenderSystem::Caps caps = april::rendersys->getCaps();
		if (glError == GL_INVALID_VALUE && !caps.npotTexturesLimited && !caps.npotTextures)
		{
			int w = this->width;
			int h = this->height;
			unsigned char* newData = this->_createPotData(w, h, data);
			glTexImage2D(GL_TEXTURE_2D, 0, this->internalFormat, w, h, 0, this->glFormat, GL_UNSIGNED_BYTE, newData);
			glError = glGetError();
			SAFE_TEXTURE_UPLOAD_CHECK(glError, glTexImage2D(GL_TEXTURE_2D, 0, this->internalFormat, w, h, 0, this->glFormat, GL_UNSIGNED_BYTE, newData));
			delete[] newData;
		}
	}

	void OpenGL_Texture::_uploadPotSafeClearData()
	{
		int size = this->getByteSize();
		unsigned char* clearColor = new unsigned char[size];
		memset(clearColor, 0, size);
		glTexImage2D(GL_TEXTURE_2D, 0, this->internalFormat, this->width, this->height, 0, this->glFormat, GL_UNSIGNED_BYTE, clearColor);
		GLenum glError = glGetError();
		SAFE_TEXTURE_UPLOAD_CHECK(glError, glTexImage2D(GL_TEXTURE_2D, 0, this->internalFormat, this->width, this->height, 0, this->glFormat, GL_UNSIGNED_BYTE, clearColor));
		delete[] clearColor;
		RenderSystem::Caps caps = april::rendersys->getCaps();
		if (glError == GL_INVALID_VALUE && !caps.npotTexturesLimited && !caps.npotTextures)
		{
			int w = this->width;
			int h = this->height;
			clearColor = this->_createPotClearData(w, h); // can create POT sized data
			glTexImage2D(GL_TEXTURE_2D, 0, this->internalFormat, this->width, this->height, 0, this->glFormat, GL_UNSIGNED_BYTE, clearColor);
			glError = glGetError();
			SAFE_TEXTURE_UPLOAD_CHECK(glError, glTexImage2D(GL_TEXTURE_2D, 0, this->internalFormat, this->width, this->height, 0, this->glFormat, GL_UNSIGNED_BYTE, clearColor));
			delete[] clearColor;
		}
	}

	bool OpenGL_Texture::_uploadToGpu(int sx, int sy, int sw, int sh, int dx, int dy, unsigned char* srcData, int srcWidth, int srcHeight, Image::Format srcFormat)
	{
		if (this->format == Image::FORMAT_PALETTE)
		{
			return false;
		}
		this->load();
		this->_setCurrentTexture();
		if (sx == 0 && dx == 0 && sy == 0 && dy == 0 && sw == this->width && srcWidth == this->width && sh == this->height && srcHeight == this->height)
		{
			this->_uploadPotSafeData(srcData);
		}
		else
		{
			if (this->firstUpload)
			{
				this->_uploadPotSafeClearData();
			}
			int srcBpp = Image::getFormatBpp(srcFormat);
			if (sx == 0 && dx == 0 && srcWidth == this->width && sw == this->width)
			{
				glTexSubImage2D(GL_TEXTURE_2D, 0, dx, dy, sw, sh, this->glFormat, GL_UNSIGNED_BYTE, &srcData[(sx + sy * srcWidth) * srcBpp]);
			}
			else
			{
				for_iter (j, 0, sh)
				{
					glTexSubImage2D(GL_TEXTURE_2D, 0, dx, (dy + j), sw, 1, this->glFormat, GL_UNSIGNED_BYTE, &srcData[(sx + (sy + j) * srcWidth) * srcBpp]);
				}
			}
		}
		this->firstUpload = false;
		return true;
	}

}
#endif
<|endoftext|>


<commit_before>// This file is part of DVS-ROS - the RPG DVS ROS Package
//
// DVS-ROS is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// DVS-ROS 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with DVS-ROS.  If not, see <http://www.gnu.org/licenses/>.

#include <ros/ros.h>
#include <fstream>
#include <ctime>

#include <dvs_msgs/Event.h>
#include <dvs_msgs/EventArray.h>

std::ofstream myfile;

// Get current date/time, format is YYYY-MM-DD.HH:mm:ss
const std::string currentDateTime() {
    time_t     now = time(0);
    struct tm  tstruct;
    char       buf[80];
    tstruct = *localtime(&now);
    // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
    // for more information about date/time format
    strftime(buf, sizeof(buf), "%Y-%m-%d_%H-%M-%S", &tstruct);

    return buf;
}

void eventsCallback(const dvs_msgs::EventArray::ConstPtr& msg) {
  for (int i=0; i<msg->events.size(); ++i) {
    myfile << (int) msg->events[i].x << " ";
    myfile << (int) msg->events[i].y << " ";
    myfile << (int) msg->events[i].polarity << " ";
    myfile << msg->events[i].time << std::endl;
  }
}

int main(int argc, char* argv[])
{
  ros::init(argc, argv, "dvs_file_writer");

  ros::NodeHandle nh;

  std::string file_name = std::string("events-" + currentDateTime() + ".txt");

  myfile.open(file_name.c_str());

  ROS_INFO("Writing events to %s", file_name.c_str());
  ros::Subscriber sub = nh.subscribe("dvs/events", 1000, eventsCallback);

  ros::spin();

  myfile.close();

  return 0;
}
<commit_msg>fix dvs_file_writer: use updated dvs_msgs timestamp format<commit_after>// This file is part of DVS-ROS - the RPG DVS ROS Package
//
// DVS-ROS is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// DVS-ROS 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with DVS-ROS.  If not, see <http://www.gnu.org/licenses/>.

#include <ros/ros.h>
#include <fstream>
#include <ctime>

#include <dvs_msgs/Event.h>
#include <dvs_msgs/EventArray.h>

std::ofstream myfile;

// Get current date/time, format is YYYY-MM-DD.HH:mm:ss
const std::string currentDateTime() {
    time_t     now = time(0);
    struct tm  tstruct;
    char       buf[80];
    tstruct = *localtime(&now);
    // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
    // for more information about date/time format
    strftime(buf, sizeof(buf), "%Y-%m-%d_%H-%M-%S", &tstruct);

    return buf;
}

void eventsCallback(const dvs_msgs::EventArray::ConstPtr& msg) {
  for (int i=0; i<msg->events.size(); ++i) {
    myfile << (int) msg->events[i].x << " ";
    myfile << (int) msg->events[i].y << " ";
    myfile << (int) msg->events[i].polarity << " ";
    myfile << (msg->events[i].ts.toNSec()/1000) << std::endl;
  }
}

int main(int argc, char* argv[])
{
  ros::init(argc, argv, "dvs_file_writer");

  ros::NodeHandle nh;

  std::string file_name = std::string("events-" + currentDateTime() + ".txt");

  myfile.open(file_name.c_str());

  ROS_INFO("Writing events to %s", file_name.c_str());
  ros::Subscriber sub = nh.subscribe("dvs/events", 1000, eventsCallback);

  ros::spin();

  myfile.close();

  return 0;
}
<|endoftext|>